硬币游戏 1(博弈)

Alice和Bob在玩这样一个游戏。给定k个数字a[1],a[2],…,a[k]。一开始,有x枚硬币,Alice和Bob轮流取硬币。每次所取硬币的枚数一定要在a[1],a[2],…,a[k]当中。Alice先取,取走最后一枚硬币的一方获胜。当双方都采取最优策略时,谁会获胜?题目假定a[1],a[2],…,a[k]中一定有1。

限制条件:

 1<=x<=10000

 1<=k<=100

 1<=a[i]<=x

输入:

 x=9

 k=2

 a={1,4}

输出:

 Alice


思路:下面来考虑当轮到自己时,还有j枚硬币时的胜负情况。

1)题目规定取光所有的硬币就获胜,这等价于轮到自己时如果没有硬币了就失败。因此,j=0时是必败态。

2)如果对于某个i(1<=i<=k),j-a[i]是必败态的话,j就是必胜态。(如果当前有j枚硬币,只要取走a[i]枚对手就必败->自己必胜)。

3)如果对于任意的i(1<=i<=k),j-a[i]都是必胜态的话,j就是必败态。(不论怎么取,对手都必胜->自己必败)。

根据这些规则,我们就能利用动态规划算法按照j从小到大的顺序计算必胜态必败态。只要看x是必胜态还是必败态,就能知道谁会获胜了。

像这样,通过考虑各个状态的胜负条件,判断必胜态和必败态,是有胜败的游戏的基础


代码:

//输入
int x,k,A[max_k];

//动态规划所用的数组
Bool win[max_x+1];

void solve()
{
    //轮到自己时没有硬币了,则失败
    win[0]=false;

    for(int j=1;j<=x;j++)
    {
         //如果可以让对手到达必败态,则必胜
         win[j]=false;
         for(int i=0;i<k;i++)
               win[j]|=A[i]<=j&&!win[j-A[i]];
    }

    if(win[x])   puts(“Alice”);
    else   puts(“Bob”);
}



  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值