题目解析
题意
输入数据的组数T,输入每组数据的个数N,输入N个整数。两个人轮流操作N个整数,每次操作可以选择将一个数减一,或是合并两个数,不能操作者算作输。Alice先操作。
思路
推理参考
dp参考
推理的结论为:
记c为石子数为1堆数,s为其他堆合并再取完的总步数。当s大于2时,c为奇数(c&1)或s为奇数(s&1)则先手必胜;当s小于2时(即s==0||s==2),c不为3的倍数(c%3!=0)先手必胜。
代码
推理
#include<stdio.h>
int n,c,s,x;
void init(){
c=s=0;
scanf("%d",&n);
for(int i=0;i<n;i++){
scanf("%d",&x);
if(x==1)
c++;
else if(x>1)
s+=(x+1);
}
if(s)
s--;
}
bool judge(){
if(s>2)
return (c&1)||(s&1);
else
return c%3;
}
int main(){
int cas;
scanf("%d",&cas);
for(int k=1;k<=cas;k++){
init();
printf("Case #%d: %s\n",k,judge()?"Alice":"Bob");
}
return 0;
}
dp(暂时还不太明白)
#include<stdio.h>
#include<string.h>
using namespace std;
int dp[60][60000];
int dfs(int i,int j){
if(dp[i][j]!=-1)
return dp[i][j];
if(j==1)
return dp[i][j]=dfs(i+1,0);
dp[i][j]=0;
if(i>=1 && !dfs(i-1,j))
dp[i][j]=1;
else if(j>=1 && !dfs(i,j-1))
dp[i][j]=1;
else if(i>=1&&j>0&&!dfs(i-1,j+1))
dp[i][j]=1;
else if(i>=2&&((j>=1&&!dfs(i-2,j+3))||(j==0&&!dfs(i-2,2))))
dp[i][j]=1;
return dp[i][j];
}
int main(){
int t,n,tmp,cas=1;
scanf("%d",&t);
memset(dp,-1,sizeof(dp));
dp[0][0]=0;
while(t--){
int a=0,b=0;
scanf("%d",&n);
for(int i=0;i<n;i++){
scanf("%d",&tmp);
if(tmp==1)
a++;
else
b+=tmp+1;
}
if(b)
b--;
printf("Case #%d: ",cas++);
if(dfs(a,b))
printf("Alice\n");
else
printf("Bob\n");
}
return 0;
}