题目:硬币游戏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; }