取石子游戏解题报告

有两堆石子,两个人轮流去取.每次取的时候,只能从较多的那堆石子里取,并且取的数目必须是较少的那堆石子数目的整数倍.最后谁能够把一堆石子取空谁就算赢.
比如初始的时候两堆石子的数目是25和7

25 7 –> 11 7 –> 4 7 –> 4 3 –> 1 3 –> 1 0

选手1取
选手2取
选手1取
选手2取
选手1取

最后选手1(先取的)获胜,在取的过程中选手2都只有唯一的一种取法。
给定初始时石子的数目,如果两个人都采取最优策略,请问先手能否获胜。

这又是一道博弈论的题,似乎是一道很基础的题,但是我依然不会做。
是这个样子的,设 ab ,则若 a2b 或b|a,则先手必胜,否则先手只有一种取法,就取下这种,看后手是否会赢,如此递归下去,时间复杂度是log级的。
考虑为什么这种情况下先手必胜。
对于b|a的情况是显然的,而若 a2b ,我们考虑a%b,假如 a%bb2 ,则显然我们取 bab1 即可令后手选法唯一且在其选过之后,留给先手的是 ab 或b|a的局面;而同样的道理,若 a%b>b2 ,我们只需取 bab 即可。
所以我们便找到了必胜态。
代码很短:

#include
#include
#include
using namespace std;
int main(){
    int n,m,tot;
    for(scanf("%d%d",&n,&m);n||m;scanf("%d%d",&n,&m)){
        if(nif(n/m>=2||n%m==0)puts("win");
        else{
            tot=0;
            do{
                n-=m;
                swap(n,m);
                ++tot;
            }while(n/m<2&&n%m);
            if(tot&1)puts("lose");
            else puts("win");
        }
    }
}

= =但是我感觉,博弈论的题证明起来好说,正面推的话就蛋疼;做题的时候。。还是先打表找规律,再深入思考吧。。不过大体思路似乎都是寻找必败态或必胜态,然后再从一个搞出另一个。

你可能感兴趣的:(博弈论)