博弈知识整理

一直害怕博弈论的题目,觉得最优不最优什么的都好扯淡啊。。。

现在终于鼓起勇气学习一下。

一、巴什博奕)

描述:有两个人 面对 一堆 物品,总共n个,每次每个人最少取一个,最多取m个,最后取完者获胜。

分析:显然,如果有小于m个,那先取者获胜;如果有m+1个,后取者总能获胜。所以某玩家只要当前形势是m+1个,或者m+1个的倍数,那么他最后肯定能获胜的啦~~

即,n = (m+1)*r + s,那么取s个就好啦~~~

变种:报数,每个人当前最多报m'个数,最少报1个数,谁先报数100个谁赢。

二、威佐夫博奕(Wythoff Game)

描述:有两堆各若干个物品,两个人轮流从某一堆或同时从两堆中取同样多的物品,规定每次至少取一个,多者不限,最后取光者得胜

暂时没遇到这样的题目。。。

三、尼姆博弈

一共有n堆,两个人每次从一堆取出石头,最后取出者赢;

变形:最后取出者输。

解决办法:

奇异态先手输,否则先手赢;单数如果变形,要判断奇偶,再按照这条规则。

描述:有三堆或者多堆若干多物品,两个人每次轮流选,每次最多不限,最少选1个,取完者获胜。。。

推荐HDOJ题目
http://acm.hdu.edu.cn/showproblem.php?pid=1907
http://acm.hdu.edu.cn/showproblem.php?pid=2509

都是变形的尼姆博弈

分析:我们用(a,b,c)表示某种局势,首先(0,0,0)显然是奇异局势,无论谁面对奇异局势,都必然失败。第二种奇异局势是(0,n,n),只要与对手拿走一样多的物品,最后都将导致(0,0,0)。仔细分析一下,(1,2,3)也是奇异局势,无论对手如何拿,接下来都可以变为(0,n,n)的情形。那么我们只要将当前局势变为奇异局势即可(任何奇异局势(a,b,c)都有a(+)b(+)c =0。)

如果我们面对的是一个非奇异局势(a,b,c),要如何变为奇异局势呢?假设 a < b< c,我们只要将 c 变为 a(+)b,即可,因为有如下的运算结果: a(+)b(+)(a(+)b)=(a(+)a)(+)(b(+)b)=0(+)0=0。要将c 变为a(+)b,只要从 c中减去 c-(a(+)b)即可。

注意,当最后一个取完的是赢者的时候,那么当前奇异态是先手必赢的状态,

当最后一个取完的是输者的时候,先判断是否都是非充裕堆(为1),全为1判断奇偶,在判断当前是否是奇异态。

例如 hdu1907,最后取完的是输者。虽然不知道为什么要判断奇偶真的不知道。。。。。。。。。。。。。。。。。。。。。。

好吧好吧,接下来就是sg函数了

上模板

int mex(set<int>&s){
    int a = 0;
    if(s.count(a))
        a++;
    return a;
}
    while(scanf("%d",&n) != EOF){
        int sg[1010] = {0};
        for(int i = 1;i <= n;i++){
            set<int>s; 
            for(int j = 0;j < numd;j++){
                if(i - d[j] < 0)
                    continue;
                s.insert(sg[i-d[j]]);
            }
            sg[i] = mex(s);
        }
        if(sg[n] == 0){
            cout << "后手" << endl;
        }
        else
         cout <<"先手" << endl; 
        
    }

猜你喜欢

转载自www.cnblogs.com/xuyanqd/p/8947308.html