找出游戏的必胜的策略(博弈论)

题目:硬币游戏1,Alice和Bob在玩这样一个游戏。给定k个数字a1,a2,···ak。 一开始,有x枚硬币,Alice和Bob轮流取硬币。每次所取硬币的枚数

一定要在a1,a2···,ak当中。Alice先取,取走最后一枚硬币的一方获胜。当双方都采取最有策略时,谁会获胜?假定a1a2···ak中一定有1

限制条件:1<=x<=10000 1<=k<=100 1<=ai<=k

样例:

输入

x=9

k=2

a={1,4}

输出

Alice

样例2

x=10

k=2

a={1,4}

输出

Bob

下面考虑轮到自己的时,还有j枚硬币的情况

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

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

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

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

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

看代码

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<cmath>
#include<math.h>
#include<algorithm>
#include<set>
#include<queue>
typedef long long ll;
using namespace std;
const ll mod=1e9+7;
#define INF 0x3f3f3f
int main()
{
    bool win[10005];
    int x,k;
    int a[110];
    cin>>x>>k;
    for(int i=0;i<k;i++)
        cin>>a[i];
    win[0]=false;//0枚硬币必败
    for(int i=1;i<=x;i++)
    {
        win[i]=false;//先初始化为为必败态
        for(int j=0;j<k;j++)
        {
            win[i]|=a[j]<=i&&!win[i-a[j]];//异或运算,有一个为必败态则为必胜态
        }
    }
    if(win[x])
        cout<<"Alice"<<endl;
    else
        cout<<"Bob"<<endl;
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/caijiaming/p/9313671.html
今日推荐