zoukankan      html  css  js  c++  java
  • 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 */

      

     

  • 相关阅读:
    每天学习Linux——日志管理
    每天学习Linux——日志查看
    每天学习Linux命令——history
    .NET中property与attribute的区别,以及反射机制
    java内部类
    java的多态
    子类构造方法
    单例模式
    重载,重写
    数据库调优的方法有那些
  • 原文地址:https://www.cnblogs.com/zzqc/p/9321130.html
Copyright © 2011-2022 走看看