付忠慶的賽後小筆記 ---Qtech交流賽

剛剛去山東理工大學的OJ看了一下問題沒有公開。。。不過幸虧大部分題能夠再其餘網站上找到 XDjava

A

四子棋 --ACM Mid-Central 1999 // 對抗搜索(要求剪枝, 容易超時)    http://poj.org/problem?id=1568ios

這個題是咱們比勝過程中嘗試的最後一道題,可是寫到一半就斷電了.....(就算不斷電我也沒有信心能A過去).....算法

其實在賽場和劍神坤隊討論的算法就沒問題,寫一個簡單的AI(就是題解所說的對抗搜索)慶幸的是我高中接觸過極其類似的----bingo,大概就是優先選擇'x'較多的排或列或對角線注意也要關注較多的'O'排或列或對角線,關於剪枝就是每排每列有不一樣的妻子就能夠終止(能夠想想爲何)網站

就是須要些大量的代碼並且保持腦子不繞  這是一項技能。。。url

這是標準程序:spa

  1 // 1999 ACM Mid-Central Regional Programming Contest
  2 // Problem A: Find the Winning Move
  3 // by Dr. Eric Shade, Computer Science Department, SMSU
  4 
  5 /**
  6  * modified by neko13
  7  */
  8 
  9 import java.io.*;
 10 import java.util.*;
 11 import static java.lang.System.*;
 12 
 13 
 14 public class Main {
 15     static final char SPACE = '.';
 16     static Scanner cin = new Scanner(in);
 17     static char[] board;
 18     
 19     public static void main(String args[]) throws IOException {
 20         // ACMIO in = new ACMIO("win.in");
 21         // PrintWriter out = new PrintWriter(new FileWriter("win.out"));
 22         
 23         for (String cmd = cin.nextLine(); cmd.equals("?"); cmd = cin.nextLine()) {
 24             String a = cin.nextLine();
 25             String b = cin.nextLine();
 26             String c = cin.nextLine();
 27             String d = cin.nextLine();
 28             String e = a+b+c+d;
 29             board = e.toCharArray();
 30 
 31             // show();
 32 
 33             int k = findForcedWin();
 34 
 35             if (k >= 0)
 36                 out.println("(" + k/4 + "," + k%4 + ")");
 37             else
 38                 out.println("#####");
 39         }
 40 
 41         out.close();
 42     }
 43 
 44 
 45     public static int findForcedWin() {
 46         for (int i = 0; i < 16; ++i)
 47             if (board[i] == SPACE && xForcedWinPlaying(i))
 48                 return i;
 49 
 50         return -1;                
 51     }
 52 
 53     
 54     public static boolean xForcedWinPlaying(int i) {
 55         board[i] = 'x';
 56         
 57         if (! isWin(i, 'x')) {
 58             for (int j = 0; j < 16; ++j) {
 59                 if (board[j] == SPACE && ! oForcedLossPlaying(j)) {
 60                     board[i] = SPACE;
 61                     return false;
 62                 }
 63             }
 64         }
 65 
 66         board[i] = SPACE;
 67         return true;
 68     }
 69 
 70     
 71     public static boolean oForcedLossPlaying(int j) {
 72         board[j] = 'o';
 73 
 74         if (! isWin(j, 'o')) {
 75             for (int i = 0; i < 16; ++i) {
 76                 if (board[i] == SPACE && xForcedWinPlaying(i)) {
 77                     board[j] = SPACE;
 78                     return true;
 79                 }
 80             }
 81         }
 82 
 83         board[j] = SPACE;
 84         return false;
 85     }
 86 
 87 
 88     public static boolean isWin(int i, char player) {
 89         int r = 4 * (i / 4);
 90         int c = i % 4;
 91         
 92         return (board[r    ] == player && board[r + 1] == player &&
 93                 board[r + 2] == player && board[r + 3] == player)
 94             || (board[c    ] == player && board[c + 4] == player &&
 95                 board[c + 8] == player && board[c +12] == player)
 96             || (board[ 0] == player && board[ 5] == player &&
 97                 board[10] == player && board[15] == player)
 98             || (board[ 3] == player && board[ 6] == player &&
 99                 board[ 9] == player && board[12] == player);
100     }
101 
102     
103     public static void show() {
104         for (int i = 0; i < 16; ++i) {
105             System.out.print(board[i]);
106             if (i%4 == 3) System.out.println();
107         }
108     }
109 }

B

幸運數code

若是A,B是幸運數那麼A+B+2也是幸運數 如今給你A B C已知A B是幸運數請問C是否是幸運數blog

//如下是原題解 我總是感受那裏錯了......難道是個人問題?ip

幸運數:c=a+b+2能夠化爲(c+2)=(a+2)+(b+2),即c=a+b;因此任何一個幸運數都是由最初的兩個幸運數所組成的,即c=x*a+y*b。ci

//另外剛開始我也理解錯了,(其實都怪領導!)覺得簡單判斷a+b+2==c就好了 可是忘記了c==a+a+2  c==b+b+2   c==(a+b+2)+a+2    c==(a+b+2)+b+2.........一系列的狀況

個人題解

咱們就先把a,b叫基本元, 不難看出c-2是由兩個基本元組成的  c-4是三個  c-6是四個。。。。 因此咱們從c-2開始 到 min(a,b)結束(不包括) 遍歷一遍,而後在每次遍歷中咱們在判斷是否能夠寫成 nx+my形式就能夠了

大概是這樣:c-2*p=nx+my (n+m=p)

代碼嘛。。。

void fun1()

{

if (有時間) 補上;

}

fun1();

//更新 ----這是標程 和個人思想不同。。。

 1 #include<iostream>
 2 
 3 using namespace std;
 4 
 5 int gcd(int x,int y)
 6 {
 7     if(!x || !y) return x>y?x:y;
 8     for(int t;t=x%y;x=y,y=t);
 9     return y;
10 }
11 
12 int main()
13 {
14     int t,a,b,c;
15     cin>>t;
16     while(t--)
17     {
18         cin>>a>>b>>c;
19         a+=2;b+=2;c+=2;
20         int g=a*b/gcd(a,b);
21         int n=c/a,m=c%a;
22         while(m%b)
23         {
24             if(n==0) break;
25             n--;
26             g-=a;
27             if(g==0) break;
28             m+=a;
29         }
30         if(m%b) cout<<"No."<<endl;
31         else cout<<"Yes."<<endl;
32     }
33     return 0;
34 }

 

C

大水題我就不說了

遍歷一遍找到最大最小下標 而後cout

D

給了 r1 r2 r3 求三角形ABC面積

呵呵,數學題我仍是....貼文獻吧

http://wenku.baidu.com/link?url=Tly1I1zFpQ9pFBRZ4kDHM9xfiBlSyuvExgdakBsk4oAw_KLxCZSKX05j4UP16P7kqd8-A6ZLHJ06tRKx9eLN2ufhsM7NQ347NC_ZiIWgna3

三角形:用向量法求出三個圓的圓心,而後便可求出三條切線。

#include<iostream>
#include<cmath>
#include<cstdio>
#define sqr(a) ((a)*(a))

using namespace std;

const double eps=1e-8;
const double pi=2.0*asin(1.0);

double getangle(double a,double b,double c)
{
    return acos((sqr(a)+sqr(b)-sqr(c))/(2*a*b));
}
double getangle(double a,double b)
{
    return asin((a-b)/(a+b));
}

typedef struct point
{
    double x,y;
    point(double xx=0,double yy=0):x(xx),y(yy){}
}vector;

point operator + (point a,vector b)
{
    return point(a.x+b.x,a.y+b.y);
}
vector operator - (point a,point b)
{
    return vector(a.x-b.x,a.y-b.y);
}
vector operator * (vector a,double b)
{
    return vector(a.x*b,a.y*b);
}
double dot(vector a,vector b)
{
    return a.x*b.x+a.y*b.y;
}
double cross(vector a,vector b)
{
    return a.x*b.y-a.y*b.x;
}
vector rotate(vector a,double b)
{
    double s=sin(b),c=cos(b);
    return vector(a.x*c-a.y*s,a.x*s+a.y*c);
}
double len(vector a)
{
    return sqrt(sqr(a.x)+sqr(a.y));
}
vector resize(vector a,double b)
{
    b/=len(a);
    return vector(a.x*b,a.y*b);
}
point inter(point a,vector v,point c,vector w)
{
    vector u=a-c;
    double t=cross(w,u)/cross(v,w);
    return a+v*t;
}

int main()
{
    double r1,r2,r3;
    int t;
    cin>>t;
    for(int i=1;i<=t;i++)
    {
        cin>>r1>>r2>>r3;
        point c1,c2,c3;
        c1=point(0,r1);
        c2=point(sqrt(sqr(r1+r2)-sqr(r1-r2)),r2);
        double a=r1+r2,b=r2+r3,c=r3+r1;
        c3=inter(c1,rotate(c2-c1,getangle(c,a,b)),c2,rotate(c1-c2,-getangle(a,b,c)));
        vector v1=vector(1,0),v2=vector(rotate(c3-c2,getangle(r2,r3))),v3=vector(rotate(c1-c3,getangle(r3,r1)));
        if(cross(v1,v2)<eps || cross(v2,v3)<eps || cross(v3,v1)<eps)
        {
            printf("No Solution!\n");continue;
        }
        point p1=point(0,0),p2=c2+resize(rotate(v2,-pi/2),r2),p3=c3+resize(rotate(v3,-pi/2),r3);
        point pa=inter(p1,v1,p3,v3),pb=inter(p2,v2,p1,v1),pc=inter(p3,v3,p2,v2);
        double s=cross(pb-pa,pc-pa)/2;
        printf("%.3lf\n",s);
    }
}

E

中心點

 給出若干個點p1 p2...pn的座標 有一個點

這個點到p1p2 ...pn距離和最小,求最小值  

原題

http://poj.org/problem?id=2420

// 模擬退火求費馬點(隨機算法, 要求精度足夠)
和個人想法徹底不一樣....我就不貼個人代碼了 徹底錯誤...

ps:費馬點就是在把這個題目的若干個點改成3個點,本題爲費馬點的推廣....

 1 #include <iostream>
 2 #include <cmath>
 3 #include <iomanip>
 4 using namespace std;
 5 
 6 double x[100], y[100];
 7 int N;
 8 
 9 double test(double xx, double yy) {
10    double total = 0;
11    for (int i=0;i<N;i++)
12       total+=sqrt(pow(x[i]-xx,2)+pow(y[i]-yy,2));
13    return total;
14 }
15 
16 int main()
17 {
18    double xx,yy;
19    double delta;
20    cin>>N;
21    for(int i=0;i<N;i++)
22     cin>>x[i]>>y[i];
23    xx = 5000;
24    yy = 5000;
25    for (delta=5000;delta>0.1;delta*=0.9) {
26       if (test(xx,yy+delta) < test(xx,yy)) yy+=delta;
27       if (test(xx,yy-delta) < test(xx,yy)) yy-=delta;
28       if (test(xx+delta,yy) < test(xx,yy)) xx+=delta;
29       if (test(xx-delta,yy) < test(xx,yy)) xx-=delta;
30    }
31    cout<<setiosflags(ios::fixed);
32    cout<<setprecision(0)<<test(xx,yy)<<endl;
33    return 0;
34 }

F

博弈論

只要判斷n==2^k-1 就好了 。。。。有一(大)部分頭文件是無用的

#include <set>
#include <map>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <queue>
#include <stack>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <cassert>
#include <cstdlib>
#include <cstring>
#include <sstream>
#include <iostream>
#include <algorithm>

using namespace std;

int grundy( int n ) {
    if( n == 1 ) return 0;
    if( n & 1 ) return grundy( n/2 );
    return n/2;
}

int main() {
    int n;
    while( scanf("%d", &n) == 1 && n ) {
        printf("%s\n", grundy(n) ? "Alice" : "Bob");
    }
    return 0;
}

G

使人眼花繚亂的Dp //有時間再消化吧!

仍是要吐槽一句考慮Dp算法的時候就怕想太多!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!其實根本不必想那麼多!!!

 1 #include <set>
 2 #include <map>
 3 #include <list>
 4 #include <cmath>
 5 #include <ctime>
 6 #include <deque>
 7 #include <queue>
 8 #include <stack>
 9 #include <cctype>
10 #include <cstdio>
11 #include <string>
12 #include <vector>
13 #include <cassert>
14 #include <cstdlib>
15 #include <cstring>
16 #include <sstream>
17 #include <iostream>
18 #include <algorithm>
19 
20 using namespace std;
21 
22 const double inf = 1e50;
23 const int NN = 10005;
24 
25 int n, P;
26 
27 struct info {
28     int p1, p2, t1, t2, w1, w2;
29 }A[NN];
30 
31 double dp[2][101][7];
32 
33 int main() {
34 
35     double cl = clock();
36     while( scanf("%d %d", &n, &P) == 2 && n ) {
37         for( int i = 1; i <= n; i++ ) scanf("%d %d %d %d %d %d", &A[i].p1, &A[i].p2, &A[i].t1, &A[i].t2, &A[i].w1, &A[i].w2);
38 
39         for( int i = 1; i <= 100; i++ ) for( int j = 0; j <= 6; j++ ) dp[0][i][j] = inf;
40         dp[0][P][0] = 0;
41         int cur = 1, prev = 0;
42         for( int k = 1; k <= n; k++ ) {
43             for( int i = 1; i <= 100; i++ ) for( int j = 0; j <= 6; j++ ) dp[cur][i][j] = inf;
44 
45             for( int i = 1; i <= 100; i++ ) for( int j = 0; j <= 6; j++ ) if( dp[prev][i][j] < inf && i >= A[k].p1 ) {
46                 int i1 = i + A[k].w1;
47                 int j1 = j + A[k].w2;
48 
49                 if( i1 * (1 << j1) >= 100 ) i1 = 100, j1 = 0;
50 
51                 double r;
52 
53                 if( i >= A[k].p2 ) r = A[k].t2;
54                 else r = A[k].t2 + (A[k].p2 - i + 0.) * ( A[k].t1 - A[k].t2 ) / (A[k].p2 - A[k].p1);
55 
56                 dp[cur][i1][j1] = min( dp[cur][i1][j1], r + dp[prev][i][j] );
57 
58             }
59 
60             for( int j = 6; j > 0; j-- ) for( int i = 1; i <= 100; i++ ) if( dp[cur][i][j] < inf ) {
61                 int i1 = min( i * 2, 100 );
62                 int j1 = j - 1;
63                 dp[cur][i1][j1] = min( dp[cur][i1][j1], dp[cur][i][j] );
64             }
65 
66             swap( cur, prev );
67         }
68         double res = inf;
69         for( int j = 6; j >= 0; j-- ) for( int i = 1; i <= 100; i++ ) res = min( res, dp[prev][i][j] );
70         if(res > inf/2) printf("Impossible\n");
71         else printf("%.2lf\n", res + 1e-11);
72     }
73 
74     cl = clock() - cl;
75     fprintf(stderr, "Total Execution Time = %lf seconds\n", cl / CLOCKS_PER_SEC);
76 
77     return 0;
78 }

H(H,I,J題號和對應題目我給忘了,可能順序不對)

有一個是給出圖形計算面積的

這道題很簡單啊 hahahahaha~

1每一行分解爲一個小圖形  最後加起來

對於每一行

     2 剛開始若是出現'.'是不計入的一直到'/'或'\'出現 才計入,然而經過這個發現‘./.\./.\.’累計有奇數個/或\就計入 不然不計入

     3 '.'表明1 '/''\'表明1/2不過能夠保證'/''\'出現次數是偶數

這樣就解出來了

fun1();

I

還有一個數論的問題

1^k+2^k+...+n^k  mod 1000000007(1和7之間幾個0忘記了,在7~10個範圍中)

只用快速冪TLE,緣由 : n<10000000000;

固然不該該傻乎乎的加啦  有通項公式的說!

這個通項公式是一個很是特別的
公式爲
1^k+2^k+...+n^k=((n+1+p)^(k+1)-p^(k+1))/(k+1)
咱們先要求一個數字p,p知足如下規則
(1+p)^(k+1)-p^(k+1)=0這個裏面首先要展開,展開後對於p,p^2 p^3等,咱們要當成一個總體對待,好比
k=1的時候
(1+p)^2-p^2=0
1+2p=0 p=-1/2
k=2的時候
(1+p)^3-p^3=0
1+3p+3p^2=0
其中p=-1/2,代入
p^2=1/6
也就是說,p p^2 p^3這些數字之間相對獨立
咱們來看看k=1的時候咱們計算的通項
1+2+..+n=((n+1+p)^2-p^2)/2=((n+1)^2+2(n+1)p)/2
p=-1/2代入
=((n+1)^2-(n+1))/2=n(n+1)/2

咱們來看k=2的時候
p=-1/2 p^2=1/6前面已經計算了,再也不重複
1^2+2^2+....+n^2=((n+1+p)^3-n^3)/3
=((n+1)^3+3(n+1)^2*p+3(n+1)p^2)3
代入p,p^2
=((n+1)^3-3(n+1)^2/2+3*(n+1)/6)/3
=(n+1)((2(n+1)^2-3(n+1)+1)/6
=(n+1)((2n^2+4n+2-3n-3+1)/6
=(n+1)(2n^2+n)/6=n(n+1)(2n+1)/6

J

還有一個是一個簡單題

素數間隙

給一個數  若是這個數是素數輸出0 不然輸出  比這個數大的素數中最小的數a1  和 比這個小的素數中最大的數a2  之差 a1-a2

兩種作法

我用的打表+暴力, 或者線性素數篩+二分

http://poj.org/problem?id=3518

代碼嘛。。。

fun1();

 

 

。。。。。結束了

while(1)

RP++;

相關文章
相關標籤/搜索