Crosses and Crosses POJ - 3537 (博弈)

题目链接:https://cn.vjudge.net/problem/POJ-3537

题目大意:

给你一个1*n的图,然后每一次你可以选一个地方放置一个‘X’,然后问你谁会先构成三个相邻的‘X’。

具体思路:

当我们在一个地方放置棋子的时候,这个位置往左边两个,往右边两个都是不能放置的,因为你先手放置的话,对手只要在这四个位置放置的话,必输。

然后每个人都要尽量的避免这个局势,所以肯定会在这个点左边两个的位置选择,这个点右边两个点开始放置。

然后对于当前的长度i。我们就可以枚举位置 j (1 < =  j < = i ),每一次是sg[j-2]^sg[i-j-2]的结果,然后sg打表就可以了。

对于这种博弈,我们可以将它看成每一次是放置一个长度为5的棋子,然后这个棋子两边的的大小是他的子状态。

AC代码:

 1 #include<iostream>
 2 #include<map>
 3 #include<string>
 4 #include<cstring>
 5 using namespace std;
 6 # define inf 0x3f3f3f3f
 7 # define ll long long
 8 const ll mod = 998244353;
 9 const int maxn = 2e3+100;
10 map<int,int>sg;// 防止越界,可以考虑用map
11 int vis[maxn];
12 void init()
13 {
14     sg[0]=0;
15     for(int i=1; i<maxn; i++)
16     {
17         memset(vis,0,sizeof(vis));
18 //        vis[sg[i-3]]=1;
19 //        vis[sg[i-4]]=1;
20 //        vis[sg[i-5]]=1;
21         for(int j=1; j<=i; j++)
22         {
23             vis[ sg[j-3] ^ sg[i-j-2]]=1;
24         }
25         for(int j=0; j<maxn; j++)
26         {
27             if(!vis[j])
28             {
29                 sg[i]=j;
30                 break;
31             }
32         }
33     }
34 }
35 
36 int main()
37 {
38     init();
39   //  freopen("hqx.in","w",stdout);
40     for(int i=1; i<=2000; i++)
41     {
42         if(!sg[i])
43             cout<<i<<endl;
44     }
45 //    for(int i=1; i<10; i++)
46 //    {
47 //        cout<<i<<" "<<sg[i]<<endl;
48 //    }
49     sg[6]=1;
50     sg[20]=1;
51     sg[42]=1;
52     sg[82]=1;
53     sg[88]=1;
54     sg[96]=1;
55     sg[116]=1;
56     sg[138]=1;
57     sg[146]=1;
58     sg[1524]=1;
59     int n;
60     while(cin>>n)
61     {
62         if(sg[n]==0)
63             cout<<"1"<<endl;
64         else
65             cout<<"2"<<endl;
66     }
67     return 0;
68 }

猜你喜欢

转载自www.cnblogs.com/letlifestop/p/10919958.html