题意:有n堆石子,一次可以拿走一个石子,或者把一堆石子放在另一个石子上。不能再次操作的人输Alice先拿。问谁赢
思路:当石子个数大于1时,可以把他们放到一堆里+1次的操作数。石子数为1时,单独考虑。
设所有只有一个石子的是A堆,其他的石子可以合并的设为B堆。
每一次操作有:
1、把A堆 的两个石子合并。加入到B堆。
2、把B堆的石子减1
3、把A堆的一个石子加入的B堆
4、把A堆的石子减1
可以用记忆化来实现。。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <stack>
using namespace std;
int dp[59][50009];
int dfs(int z,int s)
{
if(dp[z][s]!=-1) return dp[z][s];
if(z==0) return dp[z][s] = s&1;
if(z==1) return dp[1][s]=1;
if(s==1) return dp[z][s] = dfs(z+1,0);
dp[z][s] = 0;
if(!dfs(z-1,s)) dp[z][s] = 1;///直接拿走1个的
if(s>1&&!dfs(z,s-1)) dp[z][s] = 1;
if(s>1&&!dfs(z-1,s+1)) dp[z][s] = 1;
if(z>1&&!dfs(z-2,s?s+3:s+2)) dp[z][s] = 1;///合并之后加入s里
return dp[z][s];
}
int main()
{
freopen("in.txt","r",stdin);
int cas,T=1,n;
scanf("%d",&cas);
memset(dp,-1,sizeof(dp));
while(cas--)
{
scanf("%d",&n);
int z=0,s=0,t=0;
for(int i=0;i<n;i++)
{
scanf("%d",&t);
if(t==1) z++;
else s+=t+1;
}if(s>1) s--;
printf("Case #%d: %s\n",T++,dfs(z,s)?"Alice":"Bob");
}
return 0;
}