您的位置:首页 > 其它

hdu 4111 Alice and Bob(中档博弈题)★ ★

2016-09-26 10:18 453 查看
1.每堆部是1的时候,是3的倍数时输否则赢;
2.只有一堆2其他全是1的时候,1的堆数是3的倍数时输否则赢;
3.其他情况下,计算出总和+堆数-1,若为偶数,且1的堆数是偶数,则一定输;
4.不在上述情况下则赢。
#include<stdio.h>
int main()
{
int js=0;
int _case,i,n,x;
int flag1,flag2,flag,sum;
scanf("%d",&_case);
while(_case--)
{
js++;
flag1=0;
flag2=0;
flag=0;
sum=0;
scanf("%d",&n);
for(i=0;i<n;i++)
{
scanf("%d",&x);
sum+=x;
if(x==1)flag1++;
else if(x==2)flag2++;
}
if(flag1==n)
{
if(flag1%3==0)flag=1;
}
else if(flag1==n-1&&flag2==1)
{
if(flag1%3==0)flag=1;
}
else
{
if((sum+n-1)%2==0&&flag1%2==0)
flag=1;
}
printf("Case #%d: ",js);
if(flag)printf("Bob\n");
else printf("Alice\n");
}
return 0;
}


题意:有N堆石头,可以把两堆合成一堆,也可以把一堆去掉一个。
由于总数不变,最终总是要一个个拿完。那么有机会获胜的一方,肯定是先要把所有的合在一起,那么最终就拼奇偶数了。所以双方都要合并。总共就是sigma(ai)+n-1。
而且如果没有某堆只有一个的话,对方是阻挡不住的,没有取完,便被合并了。
所以就要考虑某堆只有一个的情况,单独考虑。
其中的操作包括:
把某堆只有一个的,取走
把两堆只有一个的,合并
把某堆只有一个的,合并给不是一个的
把不是一个的,取走一个
采用记忆化搜索
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define N 10005
#define LL long long
#define inf 1<<29
#define eps 1e-7
using namespace std;
int sg[55][60005];
int get_sg(int i,int j)
{
if(sg[i][j]!=-1)
return sg[i][j];
if(j==1)
return sg[i][j]=get_sg(i+1,0);
sg[i][j]=0;
//某堆只有一个的取掉
if(i>=1&&!get_sg(i-1,j))
sg[i][j]=1;
//把不是1个的取走一个
else if(j>=1&&!get_sg(i,j-1))
sg[i][j]=1;
//把1个的合并给不是1个的
else if(i>=1&&j>0&&!get_sg(i-1,j+1))
sg[i][j]=1;
//把两个1个的合并,其中注意,合并是需要一步的
else if(i>=2&&((j==0&&!get_sg(i-2,j+2))||(j&&!get_sg(i-2,j+3))))
sg[i][j]=1;
return sg[i][j];
}
int main()
{
int n,t,cas=0,k;
scanf("%d",&t);
memset(sg,-1,sizeof(sg));
while(t--)
{
scanf("%d",&n);
int one=0,sum=0;
while(n--)
{
scanf("%d",&k);
if(k==1)
one++;
else
sum+=(k+1);
}
if(sum)
sum--;
printf("Case #%d: ",++cas);
if(get_sg(one,sum))
puts("Alice");
else
puts("Bob");
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: