uva-10561-nim

  题意: 给出一个连续的棋盘,有的位置为'.',有的位置为'X',二者轮流下子,当有一方获得连续三个子的时候取胜。

  对于胜态,一种情况是当前局面出现"XX"/"X.X", 这样直接下一个子就获胜了。       

  会发现,对于".......X......."这种情况,先手绝对不能在这个X的相邻两格子里落子,否则就会形成上述的胜态给对手。

在排除了这种情况之后,我们可以把棋盘先预处理掉"禁区"部分之后再分解为一块块连续的子棋盘,这些 子棋盘相当于一个个的子问题。另一种胜态的情况就是在某一个'.'处落子之后剩余棋盘的sg值,sg[S']==0而且没有呈现出胜态1的局面,那就说明对手必败。

  初始化sg[0]=0,sg[1]=sg[2]=sg[3]=1; 显然1、2、3时候无论落子到哪,剩下的位置都不能再放子了,也就是必败态(零态).

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int n,sg[220];
 4 char s[220];
 5 bool v[220],idx[220];
 6 bool ok(){
 7     for(int i=0;i<=n-3;++i)
 8         if(s[i]=='X'&&s[i+1]=='X'&&s[i+2]=='X') return 1;
 9     return 0;
10 }
11 bool _ok(){
12     for(int i=0;i<n;++i){
13         if(s[i]=='.'){
14             s[i]='X';
15             if(ok()) {
16                 s[i]='.';
17                 return 0;
18             }
19             s[i]='.';
20         }
21     }
22     int ans=0,tmp=0;
23     for(int i=0;i<n;++i){
24         if(s[i]=='X'||
25         (i-1>=0&&s[i-1]=='X')||
26         (i-2>=0&&s[i-2]=='X')||
27         (i+1<n&&s[i+1]=='X')||
28         (i+2<n&&s[i+2]=='X')){
29             ans^=sg[tmp];
30             tmp=0;
31         }
32         else
33             tmp++;
34     }
35     //cout<<"tmp="<<tmp<<endl;
36     ans^=sg[tmp];
37     return ans==0;
38 }
39 int main(){
40     int i,j,k,t,m;
41     sg[1]=sg[2]=sg[3]=1;
42     for(i=4;i<=200;++i){
43         memset(v,0,sizeof(v));
44         for(j=1;j<=i;++j){
45             v[sg[max(0,j-3)]^sg[max(0,i-j-2)]]=1;
46         }
47         for(j=0;;j++){
48             if(!v[j]){
49                 sg[i]=j;
50                 break;
51             }
52         }
53     }
54     cin>>t;
55     while(t--){
56         cin>>s;
57         n=strlen(s);
58         memset(idx,0,sizeof(idx));
59         for(i=0;i<n;++i){
60             if(s[i]=='.'){
61                 s[i]='X';
62                 if(ok() || _ok()) idx[i]=1;
63                 s[i]='.';
64             }
65         }
66         bool can=0;
67         for(i=0;i<n;++i) if(idx[i]) can=1;
68         if(!can) puts("LOSING
");
69         else{
70             puts("WINNING");
71             for(i=0;i<n;++i)
72                 if(idx[i]){
73                     cout<<i+1;
74                     break;
75                 }
76             for(i++;i<n;++i)
77                 if(idx[i]){
78                     cout<<" "<<i+1;
79                 }
80             cout<<endl;
81         }
82     }
83     return 0;
84 }
85 /*
86 5
87 .X....XX..  ....  ..XX..  .....  ..X.X.. ...  ..XX..  ................  ..XX..  ... ..X..  .....  ..X
88 */
89 /*
90 4 
91 ..... 
92 X.....X..X.............X....X..X 
93 .X.X...X 
94 ...............................................
95 */

  

 

原文地址:https://www.cnblogs.com/zzqc/p/9321130.html