巴什博奕(Bash Game)

以前虽然也研究过博弈论,但其实还是一知半解,更多的是记住现有结论,生硬地套用而已,今天重新看了一遍巴什博奕,有了不一样的体会,终于明白了其中的原理。

问题描述:

有一堆物品,共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、南阳理工OJ的23题:取石子,最典型的巴什博奕,直接套模板

http://acm.nyist.net/JudgeOnline/problem.php?pid=23

AC代码:

#include <iostream>
using namespace std;
int main()
{
    int t;
    int n,m;
    cin>>t;
    while(t--)
    {
        cin>>n>>m;
        int flag = n%(m+1);
        if(flag)cout<<"Win"<<endl;
        else cout<<"Lose"<<endl;
    }
    return 0;
}
2、杭电2149

http://acm.hdu.edu.cn/showproblem.php?pid=2149

在最基本的巴什博奕基础上有一定的变形,稍稍绕一下就出来了

AC代码:

#include <iostream>
using namespace std;
int main()
{
    int m,n;
    while(cin>>m>>n)
    {
        if(m<=n)//如果m<=n的时候的话,先手一次性就可以取尽,因此此时从m到n的数字都是答案,这里要注意输出格式空格的问题,否则会PE
        {
            for(int i=m;i<=n;i++)
            {
                if(i==m)cout<<i;
                else cout<<" "<<i;
            }
            cout<<endl;
        }
        else    //若m>n,则按照巴什博奕的原理,判断m%(n+1),若为0,则先手败,输出“none”
        {
            int flag = m%(n+1);
            if(flag==0)cout<<"none"<<endl;
            else
            {
                cout<<flag<<endl;//若果m%(n+1)不为0,则模之后的结果就是上文分析中的s,此时先手只要拿走这个s即可
            }
        }
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值