• 博弈学习 1



    看完三位博主的文章再做了几个简单题后的简单总结。
    可以看原文,比较详细~~

    链接 1: http://blog.csdn.net/logic_nut/article/details/4711489
    链接 2: http://blog.sina.com.cn/s/blog_83d1d5c70100y9yd.html
    链接 3: http://blog.csdn.net/luomingjun12315/article/details/45479073

    几个定义与结论:

    (1)组合游戏

    1、有且仅有两个玩家
    2、两名玩家交替在 有限的移动集合(比如:取石子游戏,石子是有限的,棋盘中的棋盘大小的有限的)中对游戏进行合法的移动(不能不移动) 
    3、如果轮到某名选手移动,且这个局面的合法的移动集合为空(也就是说此时无法进行移动),则这名选手负。

    (2) Nim游戏: 
    它是组合游戏(Combinatorial Games)的一种,准确来说,属于“Impartial Combinatorial Games”(以下简称ICG)。

    通常的Nim游戏的定义是这样的:有若干堆石子,每堆石子的数量都是有限的,
    合法的移动是“选择一堆石子并拿走若干颗(不能不拿)”,如果轮到某个人时所有的石子堆都已经被拿空了,则判负(因为他此刻没有任何合法的移动)。

    (3)两个状态


    P-Position : P 指的是 Previous ,上一次移动的人有必胜策略,即先手必败
    N-Position :N 指的是 Next ,这次移动的人有必胜策略,即先手必胜

    1. 无法进行任何移动的局面(也就是terminal position)是P-position;
    2. 可以移动到P-position的局面是N-position。 
    3. 所有移动都导致N-position 的局面是P-position。

    (我的理解是:如果 所有可以移动到此局面 的局面都是N-Position ,那么此局面是 P-Position;

     如果一个局面的状态是 P-Position, 那么这个局面能够转移到的所有局面都是 N-Position

     如有不对望指正^ ^)。

    这个可以结合链接 1 原文想一想 ~

    一个结论
    (Bouton's Theorem)对于一个Nim游戏的局面(a1,a2,...,an),它是P-position当且仅当a1^a2^...^an=0,其中^表示异或(xor)运算。

    证明在链接 1 中~

    题目:HDU1846  2147 2149 2188

    几个题都是简单的巴什博奕。

    巴什博奕(Bash Game):有一堆n个物品,两人轮流从堆中取物品,每次取 x 个 ( 1 ≤ x ≤ m)。最后取光者为胜。

    HDU 1846

    1) 可以用上述的 P-Position 和 N-Position的定义解,多模拟几次就可以发现规律,然后就可愉快解题了。

    例如 n m 分别为 6 2时
    即石子有 6 颗,两人轮流取,每次可以可取 1~2 颗 。

    那么所有的状态应该是这样的:

    有x颗时  0 1 2 3 4 5 6
    Position P N N P N N P

    发现规律了咩~


    2) 也可以这样想 ,复制一段来自链接 3 的推导:

    如果 n = m + 1, 一次至多取 m 个,所以无论先取者,取了多少个,一定还剩余 x 个( 1 ≤ x ≤ m)。所以,后取者必胜。
    因此我们发现了取胜的秘诀:如果我们把 n 表示为 n = (m + 1) * r + s 。(0 ≤ s < m , r ≥ 0)。
    先取者 拿走 s 个, 后取者 拿走 k 个 (1 ≤ k ≤ m),那么先取者 再 拿走 m + 1 - k 个。
    结果还剩下 ( m + 1 ) * ( r - 1 ) 个。我们只要始终给对手留下 m + 1 的倍数,那么 先取者 肯定必胜。
    现在 我们可以知道,如果 s = 0,那么后取者必胜。 否则 先取者 必胜。

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<iostream>
    #include<string>
    using namespace std;
    int main()
    {
        int t,n,m;
        scanf("%d",&t);
        while(t--){
            scanf("%d%d",&n,&m);
            if(n%(m+1) == 0) printf("second
    ");
            else printf("first
    ");
        }
        return 0;
    }


    HDU2147

    题意:

    N*M棋盘,最初棋子在右上角,即(1,M) 每次可以往左、下、左下走一步,最后走到左下角的胜 。

    最先开始 把它看做一个类似取石子的游戏,每次可走1~2步的(走到左下算两步= =)

    然后 WA 掉了 WA 掉了 掉了 了。。

    正解是又照着定义模拟了一遍 ,找出规律,即当 N M 都是奇数的时候先手必败。

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<iostream>
    #include<string>
    using namespace std;
    int main()
    {
        int n,m;
        while(scanf("%d%d",&n,&m)!=EOF)
        {
            if(n==0 && m==0) break;
            if((n&1) && (m&1)) printf("What a pity!
    ");
            else printf("Wonderful!
    ");
        }
        return 0;
    }


    HDU2188
    与 HDU 1846 同理哟

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<iostream>
    #include<string>
    using namespace std;
    int main()
    {
        int t,n,m;
        cin>>t;
        while(t--){
            cin>>n>>m;
            if(n%(m+1)) cout<<"Grass"<<endl;
            else cout<<"Rabbit"<<endl;
        }
        return 0;
    }


    HDU 2149

    按照上面的推导 ,如果我们把 n 表示为 n = (m + 1) * r + s 。(0 ≤ s < m , r ≥ 0)。
    那么 s 就是第一次的加价 。如果加价大于本价,也就是说先手可以直接买到了 ,那么出的价就可以是 m~n这一段里的任一。
    最先开始自己没想清楚,以为 1~s 都可以,= = 后来想了下,如果不直接加到 S ,那不是给了对方可乘之机 = =

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<iostream>
    #include<string>
    using namespace std;
    int main()
    {
        int t,n,m;
        while(scanf("%d%d",&m,&n)!=EOF){
            if(m%(n+1)){
                int x = m%(n+1);            
                if(n>=m){
                    cout<<m;
                    for(int i=m+1;i<=n;i++) printf(" %d",i);
                } 
                else printf("%d",x);                        
            }
            else printf("none");    
            cout<<endl;    
        }
        return 0;
    }
  • 相关阅读:
    误删本地分支,两天的工作量差点毁于一旦,使用git reflog 有惊无险恢复
    单点登录SSO
    IdentityServer4介绍和使用
    常见的远程无线通信技术
    4G模块和DTU模块有何区别
    以太网IO控制器
    什么是无线网关,无线网关的功能
    什么是IOT网关,网关功能有哪些
    Modbus RTU和Modbus TCP的两种区别
    数据采集网关设备 如何选择数据采集网关
  • 原文地址:https://www.cnblogs.com/ember/p/5697197.html
Copyright © 2020-2023  润新知