题意是这样的,一开始给你一串数字,两个人轮流操作,操作可以分为两种。
1、每次修改一个数字,使其变为一个小于当前的非负数。
2、移除中间的某一个0以及0右边的所有数字。
使得所有数字消失的游戏者获胜。
题目有一个很关键的条件,最多只有6为,其实我们可以这样考虑这个问题。
对于每一位,最多有11种状态,0到9以及空。
所以我们可以用6个11进制表示所有的状态,这样算来时间上是可以承受的。
然后的话,就是典型的记忆化搜了,对于每一个数,枚举每一种后继的状态,然后用基本的博弈知识判断该状态是必胜还是必败。
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #define maxn 2000200 5 using namespace std; 6 7 int f[maxn],dig[8],cur,k,n; 8 char s[10]; 9 10 int dfs(int x) 11 { 12 if (x<=0) return -1; 13 if (f[x]!=0) return f[x]; 14 int tot,d; 15 for (int i=1; i<=6; i++) 16 { 17 tot=x,d=(x/dig[i])%11; 18 if (d==0) break; 19 for (int j=1; j<d; j++) 20 { 21 tot-=dig[i]; 22 if (dfs(tot)==-1) return f[x]=1; 23 } 24 if (d==1) 25 { 26 if (dfs(tot/dig[i+1])==-1) return f[x]=1; 27 } 28 } 29 return f[x]=-1; 30 } 31 32 int main() 33 { 34 memset(f,0,sizeof f); 35 dig[0]=dig[1]=1; 36 for (int i=2; i<7; i++) dig[0]+=dig[i]=dig[i-1]*11; 37 dig[0]*=10,dig[7]=dig[6]*11; 38 while (scanf("%s",s)!=EOF) 39 { 40 for (cur=0,n=strlen(s)-1,k=1; n>=0; k++,n--) 41 cur+=dig[k]*(s[n]-'0'+1); 42 if (dfs(cur)==1) printf("Yes "); 43 else printf("No "); 44 } 45 return 0; 46 }