zoukankan      html  css  js  c++  java
  • 博弈

    更新/--------------------/2019/1/25

    反尼姆博弈:

    必胜态需要满足的条件:1,当全为1的时候,判断1的个数。2,否则将全部的堆数异或起来。

    题目链接:https://cn.vjudge.net/contest/281037#problem/B

    AC代码:

     1 #include<iostream>
     2 #include<stack>
     3 #include<iomanip>
     4 #include<cmath>
     5 #include<stdio.h>
     6 #include<cstring>
     7 #include<algorithm>
     8 #include<queue>
     9 #include<vector>
    10 using namespace std;
    11 # define ll long long
    12 const int maxn =1e3+100;
    13 int main()
    14 {
    15     int T;
    16     scanf("%d",&T);
    17     while(T--)
    18     {
    19         int n;
    20         scanf("%d",&n);
    21         int ans=0,tmp;
    22         int num=0;
    23         for(int i=1; i<=n; i++)
    24         {
    25             scanf("%d",&tmp);
    26             if(tmp==1)
    27                 num++;
    28             ans^=tmp;
    29         }
    30         if(ans&&(num!=n))
    31             printf("John
    ");
    32         else if(ans==0&&num==n)
    33             printf("John
    ");
    34         else
    35             printf("Brother
    ");
    36     }
    37     return 0;
    38 }
    View Code

    bash博弈:

    一堆石子,有n个石子,每一次最多取k个,问你谁先获胜。 直接判断 n % (k +1 )是否为0,如果是0的话就是奇异局(只要对面不是傻逼的话就一定会输的局,否则就是对面赢。

    题目链接:https://cn.vjudge.net/contest/257365#problem/A

    AC代码:

     1 #include<iostream>
     2 #include<string>
     3 #include<iomanip>
     4 #include<cstring>
     5 #include<cmath>
     6 #include<map>
     7 #include<algorithm>
     8 #include<stdio.h>
     9 using namespace std;
    10 # define maxn 1000000+10
    11 # define inf 0x3f3f3f3f
    12 # define ll long long
    13 int main(){
    14 int T;
    15 scanf("%d",&T);
    16 while(T--){
    17 int n,m;
    18 scanf("%d%d",&n,&m);
    19 if(m>=n)printf("A
    ");
    20 else {
    21 if(n%(m+1))printf("A
    ");
    22 else printf("B
    ");
    23 }
    24 }
    25 return 0;
    26 
    27 }

    尼姆博弈:

    有n堆石子,每一次可以拿任意多个,问你谁拿最后一个。

    解题方法:直接将每一堆的石子异或,如果最终结果是0的话就代表是奇异局,否则就是非奇异局。

    题目链接:https://cn.vjudge.net/contest/257365#problem/C

    AC代码:

     1 #include<iostream>
     2 #include<string>
     3 #include<iomanip>
     4 #include<cstring>
     5 #include<cmath>
     6 #include<map>
     7 #include<algorithm>
     8 #include<stdio.h>
     9 using namespace std;
    10 # define maxn 1000000+10
    11 # define inf 0x3f3f3f3f
    12 # define ll long long
    13 int vis[maxn];
    14 int ans[maxn];
    15 int main()
    16 {
    17 int n;
    18 scanf("%d",&n);
    19 int temp;
    20 scanf("%d",&temp);
    21 for(int i=2;i<=n;i++){
    22 int t;
    23 scanf("%d",&t);
    24 temp=temp^t;
    25 }
    26 if(temp==0)printf("B
    ");
    27 else printf("A
    ");
    28     return 0;
    29 }

    威佐夫博弈:

    两堆石子,每一个可以从一堆里面拿任意个或者从两堆里面拿相同的个数,问你最后谁拿完。

    判断方法:如果满足 最大值和最小值的差值乘以黄金分割率等于最小值,那么当前的局面就是奇异局,否则就是非奇异局。

    题目链接:https://cn.vjudge.net/contest/257365#problem/D

    AC代码:

     1 #include<iostream>
     2 #include<string>
     3 #include<iomanip>
     4 #include<cstring>
     5 #include<cmath>
     6 #include<map>
     7 #include<algorithm>
     8 #include<stdio.h>
     9 using namespace std;
    10 # define maxn 1000000+10
    11 # define inf 0x3f3f3f3f
    12 # define ll long long
    13 # define gold (sqrt(5.0)+1.0)/2.0
    14 ll maxx(ll t1,ll t2){
    15 if(t1>t2)return t1;
    16 return t2;
    17 }
    18 ll minn(ll t1,ll t2){
    19 if(t1>t2)return t2;
    20 return t1;
    21 }
    22 int main()
    23 {
    24     ll T;        ll n,m;
    25     while(~scanf("%lld%lld",&n,&m))
    26     {
    27 
    28 
    29         ll a,b;
    30         a=maxx(n,m);
    31         b=minn(n,m);
    32         int t=(a-b)*gold;
    33        // cout<<a<<" "<<b<<" "<<t<<" "<<gold<<endl;
    34         if(b==t)printf("0
    ");
    35         else printf("1
    ");
    36     }
    37     return 0;
    38 }

    分割线/-----------------------------------------------------------------------------------------------------------------------------------/

    上面这些只是基本的模型,如果是稍微修改题意就可能套不上模板了,比如说下面这个题。

    https://cn.vjudge.net/contest/257365#problem/B

    这个时候就需要用到sg函数了,先介绍mex函数,这个函数的作用是先找到第一个在当前的区间内非负的值。

    比如说,mex[1 3 5  7] = 0 . mex[ 1 ] = 0 ,mex[2 5 7 8]= 0.mex[ 0] =1;

    然后再开始介绍sg,就拿例题作解释。

    当只有一颗石子的时候,它的后继状态只有0 (1-1=0) ,sg[1]=mex(sg[0])=1.

    当只有两颗石子的时候,他的后继状态变成了1(2-1=1),sg[2]=mex(sg[1])=0,那么这个时候就是奇异局了,也就是说只要对面不是傻逼的话,自己就一定会输。

    当只有三颗石子的时候,他的后继状态变成了2(3-1=2),0(3-3=0),所以说,sg[3]=mex(sg[2],sg[0])=2.

    以此类推,就可以推出当石子数为n的时候是不是博弈局了。一般的话如果数据量不大的话,可以直接暴力,如果数据量大的话,就可以通过sg打表找规律了。

  • 相关阅读:
    c#多线程控制
    SQL解析XML文件
    c#时间差高精度检查
    SQL Server数据库级别触发器
    c#做对比软件
    项目管理开源软件
    信息量、信息熵、交叉熵、相对熵
    GAN评价指标之mode score
    Fréchet Inception Distance(FID)
    图片的多样性之模式崩溃
  • 原文地址:https://www.cnblogs.com/letlifestop/p/10262852.html
Copyright © 2011-2022 走看看