[pixiv] https://www.pixiv.net/member_illust.php?mode=medium&illust_id=60481118
由于今天考了一道博弈的问题,我竟什么都不会!于是把之前大佬的讲稿翻出来从头学起
博弈论的基础嘛,就先不提什么SG函数了。简单的讲讲如何判断先手必胜还是必败吧。
每一个状态会有多个后继状态(即走了一步之后的状态),每一个状态都有一个属性:先手必胜 或 先手必败(先手是相对于这一状态)。
如果一个状态的后继状态中有必败态,那么当前状态的先手就可以选择那个必败的后继状态,这样下一次的先手(当前的后手)就完了。
如果一个状态的后继状态中没有必败,只有必胜态,此时不论先手选择哪一个后继状态,他都输了。
判断先手必胜还是必败,其过程类似于递归。边界就是题目中的游戏结束条件,边界的状态必定是必败态。
我们可以发现,先手的优势在于可以对局势作出调整,使其向自己希望的方向发展。当没有选择的余地时,就是听天由命了。
下面放题:
Problem Description
Two players, Stan and Ollie, play, starting with two natural numbers. Stan, the first player, subtracts any positive multiple of the lesser of the two numbers from the greater of the two numbers, provided that the resulting number must be nonnegative. Then Ollie, the second player, does the same with the two resulting numbers, then Stan, etc., alternately, until one player is able to subtract a multiple of the lesser number from the greater to reach 0, and thereby wins. For example, the players may start with (25,7):
25 7
11 7
4 7
4 3
1 3
1 0
an Stan wins.
Input
The input consists of a number of lines. Each line contains two positive integers giving the starting two numbers of the game. Stan always starts.
Output
For each line of input, output one line saying either Stan wins or Ollie wins assuming that both of them play perfectly. The last line of input contains two zeroes and should not be processed.
Sample Input
34 12
15 24
0 0
Sample Output
Stan wins
Ollie wins
Recommend
LL
题目大意
给定两个数a和b,两个人轮流操作,每个人每次可以让较大数减去较小数的整次倍。
若有一个数为0,则无法操作,无法操作者输,求先手必胜还是后手必胜。
我们发现,无论怎么做,a,b都会最终变为a%b,b的状态(假设a>=b)。当a-b>=b时,先手就有选择的余地:一次取完或只取一部分。只要有选择的余地,先手就必胜,因为他可以调整游戏回合次数。
对于这道题,每个状态可以看做只有一个后继状态,即a%b,b,从后继状态转移过来。如果a-b>=b,就把当前的转为必胜态。
还是很形象的
#include
#include
#include
using namespace std;
bool dfs(int a,int b){
if(b==0) return 0;
bool rt=dfs(b,a%b);
rt^=1;
if(a>=2*b) rt=1;
return rt;
}
int main(){
int a,b;
while(scanf("%d%d",&a,&b)){
if(a==0&&b==0) break;
if(aif(dfs(a,b)) printf("Stan wins\n");
else printf("Ollie wins\n");
}
return 0;
}