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;
}
posted @ 2018-02-01 20:14  全OI最菜  阅读(183)  评论(0编辑  收藏  举报