zoukankan      html  css  js  c++  java
  • 51 nod1072 威佐夫游戏

    1072 威佐夫游戏

    基准时间限制:1 秒 空间限制:131072 KB 分值: 0 难度:基础题
    有2堆石子。A B两个人轮流拿,A先拿。每次可以从一堆中取任意个或从2堆中取相同数量的石子,但不可不取。拿到最后1颗石子的人获胜。假设A B都非常聪明,拿石子的过程中不会出现失误。给出2堆石子的数量,问最后谁能赢得比赛。
    例如:2堆石子分别为3颗和5颗。那么不论A怎样拿,B都有对应的方法拿到最后1颗。
     
    Input
    第1行:一个数T,表示后面用作输入测试的数的数量。(1 <= T <= 10000)
    第2 - T + 1行:每行2个数分别是2堆石子的数量,中间用空格分隔。(1 <= N <= 2000000)
    Output
    共T行,如果A获胜输出A,如果B获胜输出B。
    Input示例
    3
    3 5
    3 4
    1 9
    Output示例
    B
    A
    A

    分析:首先我们根据条件来分析博弈中的奇异局势

    转载自此处

          第一个(0 , 0),先手输,当游戏某一方面对( 0 , 0)时,他没有办法取了,那么肯定是先手在上一局取完了,那么输。

    第二个 ( 1  , 2  ),先手输,先手只有四种取法,

    1)取 1 中的一个,那么后手取第二堆中两个。

    2)取 2 中一个,那么后手在两堆中各取一个。

    3)在 2 中取两个,那么后手在第一堆中取一个。

    4)两堆中各取一个,那么后手在第二堆中取一个。

    可以看出,不论先手怎么取,后说总是能赢。所以先手必输!

    第三个 ( 3 , 5 ),先手必输。首先先手必定不能把任意一堆取完,如果取完了很明显后手取完另一堆先手必输,那么

    假如看取一堆的情况,假设先手先在第一堆中取。 取 1 个,后手第二堆中取4个,变成(1 ,2)了,上面分析了是先手的必输局。

     取 2 个,后手第二堆中取3个,也变成( 1 , 2)局面了。

    假设先手在第二堆中取,取 1 个,那么后手在两堆中各取 2 个,也变成 ( 1 , 2 )局面了。

       取 2 个 ,那么后手可以两堆中都去三个, 变成 ( 0 , 0)局面,上面分析其必输。

       取  3  个,后手两堆各取 1 个 ,变成( 1 , 2)局面了。

      取 4 个,后手在第一堆中取一个,变成( 1 , 2)局面了。

    可见不论先手怎么取,其必输!

    第四个(4  , 7),先手必输。

    自己推理可以发现不论第一次先手如何取,那么后手总是会变成前面分析过的先手的必输局面。

    那么到底有什么规律没有呢,我们继续往下写。

    第四个 ( 6 ,10  )

    第五个 ( 8 ,13)

    第六个 ( 9 , 15)

    第七个 ( 11 ,18)

    会发现他们的差值是递增的,为 0 , 1 , 2, 3, 4 , 5 , 6, 7.....n

    而用数学方法分析发现局面中第一个值为前面局面中没有出现过的第一个值,比如第三个局面,前面出现了 0  1 2,那么第三个局面的第一个值为 3 ,比如第五个局面,前

    面出现了 0  1  2 3 4 5 ,那么第五个局面第一个值为6。

    再找规律的话我们会发现,第一个值 = 差值 * 1.618 

    而1.618 = (sqrt(5)+ 1) /  2 。

    大家都知道0.618是黄金分割率。而威佐夫博弈正好是1.618,这就是博弈的奇妙之处!

    然后就可以使用whythoff 模板了

     

    下面来看看威佐夫博弈常见的三类问题:

     

    1)给你一个局面,让你求是先手输赢。

    有了上面的分析,那么这个问题应该不难解决。首先求出差值,差值 * 1.618 == 最小值 的话后手赢,否则先手赢。(注意这里的1.618最好是用上面式子计算出来的,否则精

    度要求高的题目会错)

     

    2)给你一个局面,让你求先手输赢,假设先手赢的话输出他第一次的取法。

           首先讨论在两边同时取的情况,很明显两边同时取的话,不论怎样取他的差值是不会变的,那么我们可以根据差值计算出其中的小的值,然后加上差值就是大的一个值,当

    然能取的条件是求出的最小的值不能大于其中小的一堆的石子数目。

          加入在一堆中取的话,可以取任意一堆,那么其差值也是不定的,但是我们可以枚举差值,差值范围是0 --- 大的石子数目,然后根据上面的理论判断满足条件的话就是一种合理的取法。

    代码如下:

    #include<iostream>
    #include<cmath>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    int main()
    {
        int t,a,b,m,k;
        cin >> t;
        while(t --)
        {
            cin >> a >> b;
            if(a > b)
            {
                a ^= b;
                b ^= a;
                a ^= b;
            }
            m = b - a;
            k = (int) (m * (1 + sqrt(5)) / 2.0);
            printf("%s
    ",a == k ? "B" : "A");
        }
        return 0;
    }
    


  • 相关阅读:
    android模拟器上网设置
    20150916自动化测试之Appinum For Android(环境搭建之下载更新安装AndroidSDK包)
    测试部门目标
    grade 错误
    质量保证
    emma覆盖率
    python学习(二)--数据类型
    python学习(一)--python解释器
    fidder从基础到熟练
    这几天帮一个朋友解决了一点小问题(RF的有些小问题及解决过程)
  • 原文地址:https://www.cnblogs.com/lu1nacy/p/10016649.html
Copyright © 2011-2022 走看看