zoukankan      html  css  js  c++  java
  • 博弈论-巴什博奕

    问题描述:

    有一堆物品,共n个,两人轮流从这堆物品中取,规定每次至少取一个,至多m个,获胜条件分为两种,分别是最后取光者胜或者是最后取光者败。

    情形一:最后取光者胜

    分析:

                若n=m+1,则无论先手取走多少,后手一定可以一次性取走剩下的全部物品,这时后手胜;

                若n=(m+1)*r+s,且s<=m,r为任意自然数,此时先手只要先取s个,那么后手取k个(k<=m),然后先手再取m+1-k个,也就是某一组m+1个中的剩下的物品,这时候总数成为(m+1)*(r-1),所以局面成为(m+1)的任意倍,那么在接下来的游戏过程中,无论后手取多少,先手总可以取走对应的数目从而使得总数恢复到(m+1)的整数倍,一直这样下去,先手必胜。

    因此,我们总结一下,在这样的游戏规则下,求k=n%(m+1),若k不为0,则此时相当于k就是上文中提到的s,所以先手必胜,若k为0呢,则先手面临的就是当前总数为(m+1)的整数倍的情形,所以必败。

    可能我们会想:为什么一定是m+1的整数倍呢?就因为我们是从n=m+1开始分析的吗?当然不是这样的,因为以(m+1)的整数倍作为判断标准可以穷尽全部情况,假设我们修改一下上文中的公式,改成:n=(m+2)*r+s(s<=m),我们可以提取出一个r来,变成:n=(m+1)*r+s+r,所以呢,此时我们完全可以将s+r整体当做新的s,或者把它称作s',当然,此时s'很有可能已经超过了m+1,但我们就可以提取出其中(m+1)的部分来,与前面的式子合并,最后就变成了n=(m+1)*(r+1)+s'-(m+1),这就又归结到了最初的那个公式当中,所以千变万化逃不出开始的公式,也就是穷尽了所有的情况~

    情形二:最后取光者败

    求k=(n-1)%(m+1),若k=0,则后手胜,若k!=0,则先手胜。


    1.取石子(一)

    代码:

    #include <stdio.h>
    #include <memory.h>
    #include <math.h>
    #include <string>
    #include <vector>
    #include <set>
    #include <stack>
    #include <queue>
    #include <algorithm>
    #include <map>
    
    
    #define I scanf
    #define OL puts
    #define O printf
    #define F(a,b,c) for(a=b;a<c;a++)
    #define FF(a,b) for(a=0;a<b;a++)
    #define FG(a,b) for(a=b-1;a>=0;a--)
    #define LEN 1000
    #define MAX 1<<30
    #define V vector<int>
    
    using namespace std;
    
    int main(){
    //    freopen("D:\CbWorkspace\博弈论\取石子(一).txt","r",stdin);
        int T,n,m;
        I("%d",&T);
        while(T--){
            I("%d%d",&n,&m);
            int k=n%(m+1);
            if(k) puts("Win");
            else  puts("Lose");
        }
        return 0;
    }
    View Code

    理解:

    直接套用k=n%(m+1)的公式,如果k==0,后手胜,否则先手胜。


     2.Public Sale

    #include <stdio.h>
    #include <memory.h>
    #include <math.h>
    #include <string>
    #include <vector>
    #include <set>
    #include <stack>
    #include <queue>
    #include <algorithm>
    #include <map>
    
    
    #define I scanf
    #define OL puts
    #define O printf
    #define F(a,b,c) for(a=b;a<c;a++)
    #define FF(a,b) for(a=0;a<b;a++)
    #define FG(a,b) for(a=b-1;a>=0;a--)
    #define LEN 1000
    #define MAX 1<<30
    #define V vector<int>
    
    using namespace std;
    
    int main(){
        freopen("D:\CbWorkspace\博弈论\Public sale.txt","r",stdin);
        int m,n;
        while(~scanf("%d%d",&n,&m)){
            int k=n%(m+1);
            if(n<=m){
                while(k<=m){
                    O("%d",k);
                    if(k!=m) O(" ");
                    k++;
                }
                puts("");
            }else{
                if(k) O("%d
    ",k);
                else puts("none");
            }
        }
        return 0;
    }
    View Code

    理解:

    经典模型的变形


  • 相关阅读:
    windows 下的 Apache SSL证书配置
    javascript xml字符串转为json对象
    php 服务端允许跨域访问
    前端自动化构建工具 gulp 学习笔记 一、
    mysql使用select语句导出表数据时,报error 1290解决方法
    批量操作系统服务的脚本(windows关闭服务脚本)
    Dism++备份还原系统
    Win10开启蓝屏信息记录及文件查看位置的方法
    MySql 8.0服务端安装后,用navicat12连接时报2059错误_解决
    软件测试之细节功能测试_注意点
  • 原文地址:https://www.cnblogs.com/TQCAI/p/8446686.html
Copyright © 2011-2022 走看看