博弈论合集(博弈)

https://blog.csdn.net/qq_42505741/article/details/84330302

一。巴什博弈。(同余理论)

巴什博奕:只有一堆n个物品,两个人轮流从中取物,规定每次最少取一个,最多取m个,最后取光者为胜。

核心代码:

   if(n%(m+1)==0)  cout<<"后手必胜"<<endl;  
      else cout<<"先手必胜"<<endl;  

解释:一轮最多拿的就是1+m个,所以控制下去,最后的不到(1+m)的物品肯定会被后手拿到的。

例题:

HDU4764  Stone。

ac代码:

#include<algorithm>
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
typedef long long ll;
 
int main()
{
    int n,k;
    while(scanf("%d%d",&n,&k)!=EOF&&n||k)
    {
        if((n-1)%(k+1)==0)
            printf("Jiang
");
        else
            printf("Tang
");    
    }
 
} 

二。威佐夫博弈。(黄金分割)

有两堆各若干的物品,两人轮流从其中一堆取至少一件物品,至多不限,或从两堆中同时取相同件物品,规定最后取完者胜利。

解题核心就是:看两个数的差值t是不是满足  (sqrt(5)+1)/2*t==min(n1,n2);

ac代码:

  1. #include <cstdio>  
    #include <cmath>  
    #include <iostream>  
    using namespace std;  
    int main()  
    {  
        int n1,n2,temp;  
        while(cin>>n1>>n2)  
        {  
            if(n1>n2)  swap(n1,n2);  
            temp=floor((n2-n1)*(1+sqrt(5.0))/2.0);  
            if(temp==n1) cout<<"后手必胜"<<endl;  
            else cout<<"先手必胜"<<endl;  
        }  
        return 0;  
    }  

    三。尼姆博弈。(异或理论)

    有任意堆物品,每堆物品的个数是任意的,双方轮流从中取物品,每一次只能从一堆物品中取部分或全部物品,最少取一件,取到最后一件物品的人获胜。

    解题核心:把每堆物品数全部异或起来,如果得到的值为0,那么先手必败,否则先手必胜。

    ac代码:

    #include <cstdio>  
    #include <cmath>  
    #include <iostream>  
    using namespace std;  
    int main()  
    {  
        int n,ans,temp;  
        while(cin>>n)  
        {  
            temp=0;  
            for(int i=0;i<n;i++)  
            {  
                cin>>ans;  
                temp^=ans;  
            }  
            if(temp==0)  cout<<"后手必胜"<<endl;  
            else cout<<"先手必胜"<<endl;  
        }  
        return 0;  
    }  

    四。斐波那契博弈。

    有一堆物品,两人轮流取物品,先手最少取一个,至多无上限,但不能把物品取完,之后每次取的物品数不能超过上一次取的物品数的二倍且至少为一件,取走最后一件物品的人获胜。

    解题核心:先手胜当且仅当n不是斐波那契数(n为物品总数)

    ac代码:

    #include <iostream>    
    #include <string.h>    
    #include <stdio.h>    
    using namespace std;    
    const int N = 55;      
    int f[N];     
    void Init()    
    {    
        f[0] = f[1] = 1;    
        for(int i=2;i<N;i++)    
            f[i] = f[i-1] + f[i-2];    
    }      
    int main()    
    {    
        Init();    
        int n;    
        while(cin>>n)    
        {    
            if(n == 0) break;    
            bool flag = 0;    
            for(int i=0;i<N;i++)    
            {    
                if(f[i] == n)    
                {    
                    flag = 1;    
                    break;    
                }    
            }    
            if(flag) puts("Second win");    
            else     puts("First win");    
        }    
        return 0;    
    }   
    五。环形博弈。
    
    n个石子围成一个环,每次取一个或者取相邻的2个。
    
    解题核心:石子数目小于等于2 先手胜,其他 后手胜。
    
    六。对称博弈。
    
    对称博弈
    
            n个石子围成环,每次只能取相邻的1 - k个
    
              ①如果k < n:
    
                            对k=1,如果n能被2整除,则后手赢
    
                            如果k>1,后手赢(先手取什么位置后手就取对称的位置,这样保证后手永远能取到)
    
              ② 如果k>=n:
    
                            先手赢.  
     
    
    目前只了解了这几种博弈,后续会根据题目进行增添的。
    
     
    ————————————————
    版权声明:本文为CSDN博主「洋-葱」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
    原文链接:https://blog.csdn.net/qq_42505741/article/details/84330302
原文地址:https://www.cnblogs.com/lipu123/p/13276044.html