2020CCPC绵阳站Game of Cards (SG函数)

2020CCPC绵阳站Game of Cards (SG函数)

题目描述

小兔子和小马喜欢玩奇怪的纸牌游戏。现在,他们正在玩一种叫做0123游戏的纸牌游戏。桌子上有几张牌。其中c0标记为0,c1标记为1,c2标记为2,c3标记为3。小兔子和小马轮流玩游戏,小兔子先走。在每一回合中,玩家应选择两张牌,条件是两张牌上的数字之和不超过3,然后将这两张牌换成标有其和的牌。不能移动的玩家将输掉比赛。小兔子和小马在想谁会赢这场比赛。(百度翻译)

思路

找出必败态:

  1. c0 == 0 && c1 ==0
  2. c0 == 1 && c1 == 0 && c2 == 0 && c3 == 0
  3. c1 == 1 && c0 == 0 && c2 == 0

然后,SG函数打表。

代码

#include<bits/stdc++.h>
#define ll long long
#define ms(x,a) memset(x,a,sizeof(x))
using namespace std;

int sg(int c0,int c1,int c2,int c3) //1必胜 -1必败
{
    if(c0 == 0 && c1 == 0)  //只有c2,c3必败
        return -1;
    if(c0 == 1 && c1 == 0 && c2 == 0 && c3 == 0)    //只有一张0必败
        return -1;
    if(c1 == 1 && c0 == 0 && c2 == 0)   //只有一张1必败
        return -1;
    int f = 1;
    if(c0 > 0)  //一张0和其他任意一张牌组合
    {
        f = min(f,sg(c0 - 1,c1,c2,c3));
    }
    if(c1 >= 2) //用一张2替换两张1
        f = min(f,sg(c0,c1 - 2,c2 + 1,c3));
    if(c1 > 0 && c2 > 0)    //用一张3替换一张1和一张2
        f = min(f,sg(c0,c1 - 1,c2 - 1,c3 + 1));
    if(f == -1) //后继存在必败,当前必胜;否则,必败
        return 1;
    return -1;
}

int ck(ll c0,ll c1,ll c2,ll c3)
{
    if(c0 == c1 && c1 == c2 && c2 == c3 && c3 == 0)
    {
        return -1;
    }
    else
    {
        int f = 1;
        if(c3 == 0)
        {
            if(c1 == 0 && c2 == 0)
            {
                if(c0 == 0 || c0 % 2)
                {
                    f = -1;
                }
            }
            else
            {
                if(c0 % 2 == 0)
                {
                    if(c1 % 3 == 0)
                    {
                        f = -1;
                    }
                    else
                    {
                        if(c1 % 3 == 1 && c2 == 0)
                        {
                            f = -1;
                        }
                    }
                }
                else
                {
                    if(c1 % 3 == 1 && c2 > 0)
                    {
                        f = -1;
                    }
                    else if(c1 % 3 == 2 && c2 <= 1)
                    {
                        f = -1;
                    }
                }
            }
        }
        else
        {
            if(c0 % 2 == 0)
            {
                if(c1 % 3 == 0)
                {
                    f = -1;
                }
                else
                {
                    if(c1 % 3 == 1 && c2 == 0)
                    {
                        f = -1;
                    }
                }
            }
            else
            {
                if(c1 % 3 == 1 && c2 > 0)
                {
                    f = -1;
                }
                else if(c1 % 3 == 2 && c2 <= 1)
                {
                    f = -1;
                }
            }
        }
        return f;
    }
}

int main()
{
    int t;
    scanf("%d",&t);
    for(int ca = 1; ca <= t; ++ca)
    {
        ll c0,c1,c2,c3;
        scanf("%lld%lld%lld%lld",&c0,&c1,&c2,&c3);
        printf("Case #%d: ",ca);
        if(ck(c0,c1,c2,c3) == 1)
        {
            puts("Rabbit");
        }
        else
        {
            puts("Horse");
        }
    }
    return 0;
}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值