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

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;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值