2020CCPC绵阳站Game of Cards (SG函数)
- 题目描述
- 思路
- 代码
题目描述
小兔子和小马喜欢玩奇怪的纸牌游戏。现在,他们正在玩一种叫做0123游戏的纸牌游戏。桌子上有几张牌。其中c0标记为0,c1标记为1,c2标记为2,c3标记为3。小兔子和小马轮流玩游戏,小兔子先走。在每一回合中,玩家应选择两张牌,条件是两张牌上的数字之和不超过3,然后将这两张牌换成标有其和的牌。不能移动的玩家将输掉比赛。小兔子和小马在想谁会赢这场比赛。(百度翻译)
思路
找出必败态:
- c0 == 0 && c1 ==0
- c0 == 1 && c1 == 0 && c2 == 0 && c3 == 0
- 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;
}