A. 博弈
描述
阿狸和桃子在玩一个游戏,游戏规则如下。
有两堆石子,第一堆有 aa 个石子,第二堆有 bb 个石子,两个人轮流选择一堆,他可以在这一堆中取任意多的石子,规定每次至少取一个,最后取光者得胜。如果桃子先手,请问谁会赢得胜利。
Input
每行两个整数 a , ba,b 代表两堆石子。
整数长度最多不超过1000,输入数据保证不含有前导零。
Output
如果阿狸获胜输出ali,否则输出taoz1
Examples
input
1 1
output
ali
input
0 1
output
taoz1
这是一道博弈题,一开始读题读错了,以为是两人个人轮流拿一个石子,最终看谁拿到最后一个,只能说我太天真了。
然后写个程序判断a+b的值是否为奇数,要是奇数就谁先拿谁赢,偶数就谁后拿谁赢。肯定AC不了。。。。
后来我又想了想,既然决定输赢的是最后一个石子,而且每个人拿的石子为至少一个,那就是说谁都不想自己先拿完一组石子,那样的话,对方就会抢先拿完另一组的全部石子取得游戏的胜利。我想既然这样,可不可以把石子分成四部分,也就是先分成AB两组,如果AB都存在石子的话,在AB组中各标记一个石子,表示最后一个拿走的石子。
桃子肯定不会先把一组中未标记的石子全部拿走, 因为这样,阿狸就会把另一组中未标记的石子全部拿走,桃子接下来只能从两个标记过的石子中挑选,最终阿狸会拿到最后个石子取得胜利。
也就是说谁都不想先把一组中的未标记的石子先取完。这样又可以做一次标记,方法与之前的相同,我这时候觉得,这道题有点递归的意思。
我们先来看几种简单的情况,从简单的情况或许可以找到些规律。
- AB两组分别有一个石子和两个石子的时候是谁先拿谁赢。
- AB两组各两个石子的情况是谁先拿谁输。
以上两种情况是有因果关系的,情况2拿掉一个石子后就会变成情况1,也就是说存在一种必胜状态,就是情况1。
在每一个子问题中,谁都想让两组的石子数保持相等,因为等对方拿走一组的石子后就会使两组的石子数同,两组石子数不同的状态是有利于自己取胜的状态。
如果两个组的石子数不同,轮到谁了就通过取石子把两组的石子数变得相同即可,让对方来帮助自已变成有利的状态。
最终保持石子数相同会达到两组中都有两个石子的状态,这样对方只能挑选一个石子,然后自己就会变成必胜状态,取得游戏胜利。
所以说我们总结出这个游戏的一个套路就是保持两组的石子数相同
如果说初始状态是两组石子数相同,那么对方保持石子数相同即可,对方获得胜利。
通过以上所述,对于这道题,取得游戏胜利的关键是初始状态两组的石子数是否相同,由于是桃子先选,所以如果石子数不同,就是桃子赢,相同即阿狸赢。还需要注意的是“整数长度最多不超过1000,输入数据保证不含有前导零。”这个数据是很大的,无论使用何种变量类型都会超过范围,而这道题只是单纯的判等,所以我们使用字符串就好了。
还有再插一嘴,这道题的原型叫做威佐夫博弈,可以百度看到它的证明过程,以上我所说的并不严谨,但是结论是对的,在此附上相关证明链接对证明过程不再赘述:
百度百科-威佐夫博弈
CSDN-博客1
CSDN-博客2
以下AC代码:
#include<iostream>
#include<string>
using namespace std;
int main(){
string a,b;
cin>>a>>b;
if(a==b){
cout<<"ali"<<endl;
}
else{
cout<<"taoz1"<<endl;
}
}