SSLZ-YC 游戏
题目大意:
两个核武器科学家Patrick和Roland玩起了跟核武器有关的游戏,游戏一开始在桌子上放了一些核材料,两个人轮流玩,Patrick先玩。游戏规则是每次玩家可以从这些核材料里选一些材料放到反应堆去。只有A,B,C,D四种材料,而且允许的反应只有以下5种:
1. AABDD
2. ABCD
3. CCD
4. BBB
5. AD
当某个人选不到材料进行反应时就输了,大家要知道两个人都是绝顶聪明的。
思路:
这道题的方法是记忆化搜索。 我们用f[a][b][c][d]表示A,B,C,D分别剩余a个,b个,c个,d个时的获胜者。于是我们可以递推出5种不同的取法(如题)到达这一步。但是若f[a-2][b-1][c][d-2]为Patrick获胜,那么f[a][b][c][d]则为Roland获胜。
代码:
#include <cstdio>
using namespace std;
int f[61][61][61][61],a[6],b[6],c[6],d[6],n,A,B,C,D;
void csh() //初始化
{
a[1]=2; a[2]=1; a[3]=0; a[4]=0; a[5]=1;
b[1]=1; b[2]=1; b[3]=0; b[4]=3; b[5]=0;
c[1]=0; c[2]=1; c[3]=2; c[4]=0; c[5]=0;
d[1]=2; d[2]=1; d[3]=1; d[4]=0; d[5]=1;
f[0][0][0][0]=2; //如果没有材料,则为Roland获胜
}
int dfs(int aa,int bb,int cc,int dd) //记忆化搜索
{
if(f[aa][bb][cc][dd]) return f[aa][bb][cc][dd];
for (int i=1;i<=5;i++)
if (aa>=a[i]&&bb>=b[i]&&cc>=c[i]&&dd>=d[i])
if(dfs(aa-a[i],bb-b[i],cc-c[i],dd-d[i])==2) return f[aa][bb][cc][dd]=1;
//递归+判断输赢
return f[aa][bb][cc][dd]=2; //否则后者获胜
}
int main()
{
freopen("j5.in","r",stdin);
freopen("j5.out","w",stdout);
csh();
scanf("%d",&n);
for (int i=1;i<=n;i++)
{
scanf("%d%d%d%d",&A,&B,&C,&D);
if (dfs(A,B,C,D)==1) printf("Patrick\n"); //开始搜索
else printf("Roland\n"); //输出
}
return 0;
}