zoukankan      html  css  js  c++  java
  • 51nod 1069 Nim游戏 + BZOJ 1022: [SHOI2008]小约翰的游戏John(Nim游戏和Anti-Nim游戏)

    首先,51nod的那道题就是最简单的尼姆博弈问题。

    尼姆博弈主要就是判断奇异局势,现在我们就假设有三个石子堆,最简单的(0,n,n)就是一个奇异局势,因为无论先手怎么拿,后手总是可以在另一堆里拿走相同的石子数。

    再看另外一个奇异局势(1,2,3):

    ①如果先手拿第一个石子堆,那么后手可以形成(0,2,2)的局势,先手必败。

    ②如果先手拿第二个石子堆的1个石子,那么后手可以形成(1,1,0)的局势,先手必败。

    ③如果先手拿第二个石子堆的2个石子,那么后手可以形成(1,0,1)的局势,先手必败。

    后面的同理分析即可。

    现在我们需要考虑的是如何判断一个局势是否是奇异局势?

    奇异局势的判断就是所有堆的值异或起来,如果最后等于0就是奇异局势,如果不是则不是奇异局势(异或的原理就是对于二进制的每一位进行运算,如果某一位最后为0,那么就说明该位上有偶数次1出现,偶数次说明什么呢?说明先手在某堆石子操作后,后手总能在另一堆石子里去做相对应的操作)。

    那么如果先手面对的是非奇异局势,也只需要一步就可以变成奇异局势,将所有堆的值异或起来(除去最大堆),再用最大堆-该异或值,就是所拿石子数。

     1 #include<cstdio>
     2 using namespace std;
     3 
     4 int n;
     5 
     6 int main()
     7 {
     8     while(~scanf("%d",&n))
     9     {
    10         int ans=0;
    11         for(int i=0;i<n;i++)
    12         {
    13             int x; scanf("%d",&x);
    14             ans^=x;
    15         }
    16         if(ans) puts("A");
    17         else puts("B");
    18     }
    19     return 0;
    20 }
    View Code

    接下来介绍一下anti-nim游戏,它的话就是取到最后一个石子输。

    对于这种题目,它有一个专门的SJ定理:(具体的话就参见论文吧)

    对于一个Anti-Nim游戏,只要有以下两条条件之一,先手必胜:

    1.游戏的总SG函数为0且任意子游戏的SG函数不超过1;

    2.游戏的总SG函数不为0且至少存在一个子游戏的SG函数超过1。

     1 #include<iostream>
     2 #include<algorithm>
     3 #include<cstring>
     4 #include<cstdio>
     5 #include<vector>
     6 #include<stack>
     7 #include<queue>
     8 #include<cmath>
     9 #include<map>
    10 #include<set>
    11 using namespace std;
    12 typedef long long ll;
    13 typedef pair<int,int> pll;
    14 const int INF = 0x3f3f3f3f;
    15 const int maxn = 50 + 5;
    16 
    17 int n;
    18 
    19 int main()
    20 {
    21     //freopen("in.txt","r",stdin);
    22     int T;
    23     scanf("%d",&T);
    24     while(T--)
    25     {
    26         int sum=0;
    27         scanf("%d",&n);
    28         bool flag=false;
    29         for(int i=1;i<=n;i++)
    30         {
    31             int x; scanf("%d",&x);
    32             sum^=x;
    33             if(x>1)  flag=true;
    34         }
    35         if((!sum && !flag) || (sum && flag))  puts("John");
    36         else puts("Brother");
    37     }
    38     return 0;
    39 }
    View Code

     

  • 相关阅读:
    完整java开发中JDBC连接数据库代码和步骤
    网上书城分类Category模块
    网上书城小工具(也适用于其他项目)
    java总结第四次//常用类
    java总结第三次//类和对象2、3
    java 视频中截图
    java 截屏 类似于 QQ截屏
    java 图片压缩
    删除putty的session 以及 putty的颜色设置值
    jQuery 截取double数据 重新赋值
  • 原文地址:https://www.cnblogs.com/zyb993963526/p/7649674.html
Copyright © 2011-2022 走看看