这里有2种方法:
方法一:求SG函数
sg[i][j]:i表示1的个数,j表示合并操作的步数。
这共有4种操作:
1.消除一个1;
2.减掉一个1;
3.合并2个1;
4.把1合并到另外不是1中。
代码如下:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<iostream> 2 #include<stdio.h> 3 #include<algorithm> 4 #include<iomanip> 5 #include<cmath> 6 #include<cstring> 7 #include<vector> 8 using namespace std; 9 int dp[60][50040]; 10 int dfs(int a,int b) 11 { 12 if(dp[a][b]!=-1) return dp[a][b]; 13 if(b==1) return dp[a][b]=dfs(a+1,0); 14 dp[a][b]=0; 15 if(a>=1&&!dfs(a-1,b)) dp[a][b]=1; 16 else if(b>=1&&!dfs(a,b-1)) dp[a][b]=1; 17 else if(a>=2&&((b>=1&&!dfs(a-2,b+3))||(b==0&&!dfs(a-2,2)))) dp[a][b]=1; 18 else if(a>=1&&b>=1&&!dfs(a-1,b+1)) dp[a][b]=1; 19 return dp[a][b]; 20 } 21 int main(){ 22 int i,t,ca=0,n,k,one,other; 23 memset(dp,-1,sizeof(dp)); 24 scanf("%d",&t); 25 while(t--){ 26 scanf("%d",&n); 27 other=one=0; 28 for(i=0;i<n;i++){ 29 scanf("%d",&k); 30 if(k==1) one++; 31 else other+=k+1; 32 } 33 if(other) other--; 34 int ff=dfs(one,other); 35 printf("Case #%d: ",++ca); 36 if(ff) puts("Alice"); 37 else puts("Bob"); 38 } 39 return 0; 40 }
方法二:
可以分四种情况:
1.只有1的时候,1的个数为3的倍数则必输否则赢;
2.只有1个2和若干1时,1的个数为3的倍数则必输否则赢;
3.其他情况,计算总和+个数-1,如果是奇数则必赢否则输;
4.剩下的就赢了。
代码如下:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<stdio.h> #define I(x) scanf("%d",&x) int main(){ int i,t,n,s,k,j=0,m; bool f; I(t); while(t--){ I(m); for(s=n=f=i=0;i<m;i++){ I(k); if(k==1) n++; s+=k; } if(n==m) f=n%3; else if(s-n==2) f=n%3; else if((s+m-1)&1) f=1; else f=n&1; printf("Case #%d: ",++j); puts(f?"Alice":"Bob"); } return 0; }