Hdu1404 Digital Deletions(暴力SG博弈)
Digital Deletions
题意:一串由0~9组成的数字,可以进行两个操作:1、把其中一个数变为比它小的数;2、把其中一个数字0及其右边的所以数字删除。两人轮流进行操作,最后把所以数字删除的人获胜,问前者胜还是后者胜。字符串长度为1-6,前者胜输出Yes,否则输出No.
题解:具体看代码。
1 #include<iostream>
2 #include<cstdio>
3 #include<cstring>
4 #include<algorithm>
5 using namespace std;
6 const int maxn=1e6+10;
7 char s[10];
8 int sg[maxn];
9 int get_sg(int x)
10 {
11 int t=x;
12 int cnt=0;
13 int num[10]={0};
14 while(t)
15 {
16 num[++cnt]=t%10;
17 t/=10;
18 }
19 int flag=0;
20 for(int i=1;i<=cnt;i++)//最外层for循环控制x的每一位的所有操作
21 {
22 if(num[i]==0)//当前这一位为0,那么对这一位能进行的操作只能是抹去
23 {
24 //以下判断将该位抹去后的状态是否为必胜态
25 int k=0;
26 for(int j=cnt;j>i;j--)
27 {
28 k=k*10+num[j];
29 }//例如x=970,我们求得K=97(97是将0抹去后的状态)
30 if(!sg[k])//如果97为必败态,那么970一定为必胜态
31 flag=1;
32 }
33 else//当前这一位不为0
34 {
35 //例如x=452 它一步可以到达的状态有 451 450 442 432 422 412 402 352 252 152 (052)
36 //因为如果第一位是0的话,面对这种状态的人必胜,我们需要判断它可以一步到达的状态是否有必败态,所以不用考虑第一位是0的
37 //反而如果考虑了第一位是0就会出错 比如402,对于第一位来说,它的下一步状态之一是002,是必胜态,但是我们再判断的时候,判断的
38 //其实是2,2是必败态,因此出错。
39 if(i==cnt)//即为第一位
40 {
41 for(int j=1;j<num[i];j++)
42 {
43 int p=0;
44 for(int k=cnt;k>=1;k--)
45 {
46 if(k==i)
47 {
48 p=p*10+j;
49 }
50 else
51 {
52 p=p*10+num[k];
53 }
54 }
55 if(sg[p]==0)
56 {
57 flag=1;
58 break;
59 }
60 }
61
62 }
63 else
64 {
65 for(int j=0;j<num[i];j++)
66 {
67 int p=0;
68 for(int k=cnt;k>=1;k--)
69 {
70 if(k==i)
71 {
72 p=p*10+j;
73 }
74 else
75 {
76 p=p*10+num[k];
77 }
78 }
79 if(sg[p]==0)
80 {
81 flag=1;
82 break;
83 }
84 }
85 }
86 }
87 if(flag)
88 break;
89 }
90 if(flag)
91 return 1;
92 else
93 return 0;
94 }
95 int main()
96 {
97 int n;
98 memset(sg,-1,sizeof(sg));
99 sg[0]=1;
100 sg[1]=0;
101 for(int i=2;i<maxn;i++)
102 {
103 sg[i]=get_sg(i);
104 }
105 while(~scanf("%s",s))
106 {
107 if(s[0]=='0')
108 {
109 puts("Yes");
110 continue;
111 }
112 else
113 {
114 int sum=0;
115 int len=strlen(s);
116 for(int i=0;i<len;i++)
117 {
118 sum=sum*10+s[i]-'0';
119 }
120 if(sg[sum])
121 puts("Yes");
122 else
123 puts("No");
124 }
125 }
126 }