zoukankan      html  css  js  c++  java
  • 博弈论--Nim游戏

    Nim游戏是博弈论中最经典的模型(之一),它又有着十分简单的规则和无比优美的结论 Nim游戏是组合游戏(Combinatorial Games)的一种,准确来说,属于“Impartial Combinatorial Games”

    Nim游戏具体游戏规则为:有n堆石子,两名选手,每个选手可以拿一堆石子中的任意多个,谁面对无石子可拿的情况时就为负。

    定义:先手必败状态 定义为走不到任何一个必败状态,为状态P

       先手必胜状态 定义为能够走到一个必败状态,为状态N

     根据定义出发,模拟(2,2)的必败场景

     因为(0,2)能到(0,0),所以(0,2)为N状态

    因为(1,1)只有(0,1)一个后继态,而(0,1)为N态,所以(1,1)为P态。所以(1,2)为N态

    所以(2,2)有且只有两个N态,所以(2,2)是一个P态

    即面对(2,2)的情况,先手必败。

    既然如此,给定n堆石子就可以求出当前状态是N或P,但是时间复杂度过高哪怕用上记忆化搜索或者DP,时间复杂度为O ( max(a1,a2...an) ),而0<=ai<=1e9

    显然是不能再1s钟内算出答案。

    所以数学家们想到了一个绝妙的方法:利用异或

    记 t = a1^a2^a3^...^an

    若t=0,则当前状态为P,即先手必败

    否则则为N,即先手必胜

    证明:若需证明上述定理,则需要证明

    (1)最终的全零态被判定为P态

    (2)被判定为N态的一定可以移动到某一个P态

    (3)被判定为P态的,一定不能移动到某一个P态

     

     所以可以直接通过上边的定理得出当前是一个P态或者N态

     1 #include<iostream>
     2 using namespace std;
     3 int main(void){
     4     int n;
     5     cin>>n;
     6     int res;
     7     cin>>res;
     8     for(int i=1;i<n;i++){
     9         int t;
    10         cin>>t;
    11         res^=t;
    12     }
    13     if(res==0){
    14         cout<<"No";
    15     }else{
    16         cout<<"Yes";
    17     }
    18 }

    Nim游戏变种--台阶Nim游戏

    题目:https://www.acwing.com/problem/content/894/

     1 #include<iostream>
     2 using namespace std;
     3 int main(void){
     4     int n;
     5     cin>>n;
     6     int res=0;
     7     for(int i=0;i<n;i++){
     8         int x;
     9         cin>>x;
    10         if(i%2==0)
    11             res^=x;
    12     }
    13     if(res) puts("Yes");
    14     else puts("No");
    15     return 0;
    16 }
  • 相关阅读:
    史上最强大vimrc
    Linux 宿主目录、根目录及/home区别
    ubuntu配置软件源
    Lex入门2
    域名服务器(DNS)工作原理
    SQL Server 2005脚本编辑窗口不能使用Enter,Backspace, Insert等按键
    建立windows2003 域名服务器
    JavaScript操作cookie
    VS2008下设置断点调试JavaScript (IE)
    DNS域名服务器原理与架设(Bind on Linux)
  • 原文地址:https://www.cnblogs.com/greenofyu/p/14173670.html
Copyright © 2011-2022 走看看