题目:硬币游戏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#include #include<string.h> #include #include #include #include<set> #include 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 ) cin>>a[i]; win[0]=false;//0枚硬币必败 for(int i=1;i<=x;i++) { win[i]=false;//先初始化为为必败态 for(int j=0;j ) { win[i]|=a[j]<=i&&!win[i-a[j]];//异或运算,有一个为必败态则为必胜态 } } if(win[x]) cout<<"Alice"<<endl; else cout<<"Bob"<<endl; return 0; }
2、A Funny Game
题目:n枚硬币排成一个圈。Alice和Bob轮流从中取一枚或两枚硬币。不过,取两枚时,所取的两枚硬币必须是连续的。硬币取走之后留下空位
,相隔空位的硬币视为不连续。Alice开始先取,取走最后一枚硬币的一方获胜。当双方都采取最优策略时,谁会获胜
0<=n<=1000000
输入
n=1
输出
Alice
输入
n=3
输出
Bob
n高达1000000,考虑到还有将连续部分分裂成几段等的情况,状态数非常的多,搜索和动态规划都难以胜任。需要更加巧妙地判断胜败关系
首先,试想一下如下情况。能够把所有硬币分解成两个完全相同的状态,是必败态还是必胜态呢?
事实上,是必败态。不论自己采取何种策略,对手是要在另一组采取相同的策略,就又回到了分成两个相同的组的状态了
不断循环下去,总会轮到自己没有硬币了。也就是说,因为对手取走了最后一枚硬币而败北
接下来,回到正题。Alice在第一步取走了一枚或者两枚硬币之后,原本成圈的硬币变成了长度为n-1或者n-2的链。这样只要Bob在中间位子
根据链长的奇偶性,取走一枚或者两枚硬币,就可以把所有硬币正好分为两个长度相同的链
这也正如我们前面说的必败态。也就是说Alice必败,Bob必胜,只不过当n<=2时,Alice可以在第一次取光,所以胜利的是Alice。在这类游戏中
做出对称的状态再完全模仿对手的策略常常是有效的
看代码
#include#include #include<string.h> #include #include #include #include<set> #include typedef long long ll; using namespace std; const ll mod=1e9+7; #define INF 0x3f3f3f int main() { int n; cin>>n; if(n<=2) cout<<"Alice"<<endl; else cout<<"Bob"<<endl; return 0; }
3、Euclid's Game
让我们看一下这个以辗转相除法为基础的游戏
给定两个整数a,b。Stan和Ollie轮流从较大的数字中减去较小数字的倍数。这里的倍数是指1倍,2倍这样的正整数倍,并且相减后的结果不能
小于零。Stan先手,在自己的回合将其中一个数变为0的一方获胜。当双方都采取最优策略时,谁会获胜?
输入
a=64,b=12
输出
Stan wins
输入
a=15,b=24
输出
Ollie wins
让我们来找找看该问题中必胜态和必败态。首先,如果a>b则交换,假设a
此时,a和b的关系按照自由度的观点。可以分为以下两类