zoukankan      html  css  js  c++  java
  • 【博弈专题】解题报告

    HDU1079 Calendar Game

      设k=m+d,容易知道,终态2001.11.4为P局面(后手胜),此时k=11+4=15,为奇态。我们不妨假设:如果k为寄态,先手胜;k为偶态,后手胜。对于一年中某个日子,其后一天或者下个月同一天都是k的奇偶转换,对于先手来说,如果此时k为奇态,则必胜;如果为偶态,则看是否能给后手也留下一个偶态让其处于N局面(先手胜)。一年中可以偶态到偶态的日子只有4个:4.30、6.30、9.30、11.30。这4个日子虽然k为偶数,但也属于先手胜局面,因为这四个日子能给对方留下k偶态。

    #include <stdio.h>
    #include <string.h>
    
    int main()
    {
        int y, m, d, t;
        scanf("%d", &t);
        while(t--)
        {
            scanf("%d%d%d", &y, &m, &d);
            int k = m + d;
            if(((m==4||m==6||m==9||m==11)&&d==30)||k % 2 == 0)
                puts("YES");
            else
                puts("NO");
        }
        return 0;
    }
    View Code

    HDU1564 Play a game

      n为偶数则8600胜,n为奇数则ailyanlu胜。

    证明:如下图

      对于两个图,我们用1x2的矩形进行覆盖,当一个人走到一个新的1x2方块时,另一个人为必胜者,因为他总可以走该方块的另一个格子。

    #include <stdio.h>
    #include <string.h>
    
    int main()
    {
        int x;
        while(scanf("%d", &x) != EOF && x)
        {
            if(x % 2 == 0)
                puts("8600");
            else
                puts("ailyanlu");
        }
        return 0;
    }
    View Code

    HDU1846 Brave Game

      最经典的取石子游戏了,当“n==k*(m+1)(k为整数)”成立时,为后手胜局面,其他局面为先手胜局面。分析从略。

    #include <stdio.h>
    #include <string.h>
    
    int main()
    {
        int t, n, m;
        scanf("%d", &t);
        while(t--)
        {
            scanf("%d%d", &n, &m);
            if(n % (m+1) == 0)
                puts("second");
            else
                puts("first");
        }
        return 0;
    }
    View Code

    HDOJ1847 Good Luck in CET-4 Everybody!

      直接手动打表“1 1 0 1 1 0 1 1 0 1 1 0...”,当n为3的倍数时后手胜,其他情况为先手胜。

    #include <stdio.h>
    #include <string.h>
    
    int f[1005];
    
    void init()
    {
        for(int i = 1; i <= 1000; i++)
            f[i] = !((i % 3) == 0);
    }
    
    int main()
    {
        int n;
        init();
        while(scanf("%d", &n) != EOF)
            printf("%s
    ", f[n] ? "Kiki" : "Cici");
        return 0;
    }
    View Code

    HDOJ2147 kiki's game

      棋盘中能向左、向下或左下方移动,那么谁先到达左下角位置,谁就赢了。

      这道题我是逐步逐行推导的:

      1. 如果棋盘只有一行,那么胜负由列数的奇偶性判断;

      2. 如果棋盘有两行,则先手必胜,证明如下:

        设起始点为s,s左下方的格子为k,先手可以控制谁到达k(让自己到达k的话直接一步到k,让对方到达k的话向下走而对方必须向左走)。证毕。

      那么,我们可以推导出一个这样的胜负图:

    ... ... ... ... ... ...
    1 1 1 1 1 ...
    0 1 0 1 0 ...
    1 1 1 1 1 ...
    0 1 0 1 0 ...

      格子中0表示后手胜,1表示先手胜。

    #include <stdio.h>
    #include <string.h>
    
    int main()
    {
        int n, m;
        while(scanf("%d%d", &n, &m) != EOF && n + m)
        {
            if((n % 2 == 0) || ((n % 2 == 1) && (m % 2 == 0)))
                puts("Wonderful!");
            else
                puts("What a pity!");
        }
        return 0;
    }
    View Code

    HDU2516 取石子游戏

      一直推,多推几个,发现规律了吗?没错,就是斐波那契数列。

    #include <stdio.h>
    #include <string.h>
    #define N 45
    int f[N];
    
    void init()
    {
        f[1] = 2;
        f[2] = 3;
        for(int i = 3; i < N; i++)
            f[i] = f[i-1] + f[i-2];
    }
    
    int main()
    {
        int n;
        init();
        while(scanf("%d", &n) != EOF && n)
        {
            bool flag = false;
            for(int i = 1; i < N; i++)
            {
                if(f[i] == n)
                {
                    flag = true;
                    break;
                }
                if(n < f[i])
                    break;
            }
            if(flag) puts("Second win");
            else puts("First win");
        }
        return 0;
    }
    View Code

    HDU2897 邂逅明下

      把(p+q)作为一个单位,因为假如一个人取x个,另外一个人总可以取y个使得(x+y)== (p+q)。设k=n%(p+q),那么我们只需要判断k的情况下的胜负情况。不难推出当1<=k<=p时先手负,其他局面都是先手胜。

    #include <stdio.h>
    #include <string.h>
    
    int main()
    {
        int n, p, q;
        while(scanf("%d%d%d", &n, &p, &q) != EOF)
        {
            int k = n % (p + q);
            if(k != 0 && k <= p)
                puts("LOST");
            else
                puts("WIN");
        }
        return 0;
    }
    View Code

    POJ1740 A New Stone Game

      楼教男人八题中的博弈题。一步一步分析下来就不难了。

      1. 如果只有一堆,先手可以全部拿完然后胜利;

      2. 如果有两堆,石子数分别为x和y,那么

        1) 当x==y时,先手负,因为后手可以和先手作出同样的动作;

        2) 当x!=y时,先手胜,因为先手可以再x和y中大的那一堆石子取出k颗使得x==y,也就是让后手来面对必败局面;

      3. 如果有三堆,石子数分别为x,y,z,那么

        1) 当x,y,z中至少有两个是相等的时候,先手胜,因为先手可以取走一堆石子使得剩下的两堆石子数相等,那么情况就如同1

        2) 当x,y,z互不相等时,不妨设x < y < z,那么我们在z中取走z-(y-x)颗石子,然后将剩下的y-x颗石子放到x堆里,此时有(y, y)的两堆石子,那么情况如2

      综上所述,只有在石子的堆数为偶数且石子数两个两个相等情况下,先手负,其他局面都是先手胜局面。

    #include <stdio.h>
    #include <string.h>
    #include <algorithm>
    
    int a[105];
    
    int main()
    {
        int n;
        while(scanf("%d", &n) != EOF && n)
        {
            for(int i = 0; i < n; i++)
                scanf("%d", &a[i]);
            if(n & 1) 
            {
                puts("1");
                continue;
            }
            std::sort(a, a+n);
            bool flag = false;
            for(int i = 0; i < n; i+=2)
            {
                if(a[i] != a[i+1])
                {
                    flag = true;
                    break;
                }
            }
            printf("%d
    ", flag);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    深入探索 高效的Java异常处理框架
    Java多线程调试如何完成信息输出处理
    WebKit学习资源
    WebKit阅读起步
    Redis学习资源
    webkit在vs2008中编译
    【转】推荐几本学习MySQL的好书-MySQL 深入的书籍
    Mysql: 开启慢查询日志[ERROR] unknown variable 'log-slow-queries'处理办法
    Linux top命令详解
    eclipse svn同步过滤掉某些不需要同步的文件
  • 原文地址:https://www.cnblogs.com/huangfeihome/p/3651619.html
Copyright © 2011-2022 走看看