ZOJ2725_Digital Deletions

题意是这样的,一开始给你一串数字,两个人轮流操作,操作可以分为两种。

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\n");
43             else printf("No\n");
44     }
45     return 0;
46 }

 

posted @ 2013-10-18 19:33  092000  阅读(345)  评论(0编辑  收藏  举报