博弈论基础

举报
兔老大 发表于 2021/04/23 00:04:56 2021/04/23
【摘要】 博弈论总结 什么是博弈论: 多人进行博弈,假设每个人都采取最优策略,一定有一个人胜出,在知道初态及规则的情况下,求解出 何人胜出的一类问题的理论及方法。 博弈论的一些性质 P点:必败点,N点:必胜点 (1)无法进行任何移动的局面(也就是terminal position)是P-position; (2)可以移动到P-position的局面是N-position;...

博弈论总结

什么是博弈论:

多人进行博弈,假设每个人都采取最优策略,一定有一个人胜出,在知道初态及规则的情况下,求解出

何人胜出的一类问题的理论及方法。

博弈论的一些性质

P点:必败点,N点:必胜点

1)无法进行任何移动的局面(也就是terminal position)是P-position

2)可以移动到P-position的局面是N-position

3)所有移动都导致N-position的局面是P-position

巴什博奕:

介绍:只有一堆n个物品,两个人轮流从中取物,规定每次最少取一个,最多取m个,最后取光者为

胜。

必定可以写成该式子 n=k*(m+1)+r

结论:若r=0,则先手必败,否则先手必胜。


      if(n % (m + 1) == 0)
      cout<<"后手必胜"<<endl;
      else
      cout<<"先手必胜"<<endl;
  
 

威佐夫博弈:

介绍:有两堆各若干的物品,两人轮流从其中一堆取至少一件物品,至多不限,或从两堆中同时取相同

件物品,规定最后取完者胜利。

结论:若两堆物品的初始值为(xy),且x<y,则另z=y-x

w=int[((sqrt5+1/2*z ];(中间为熟知的黄金分割比)

w=x,则先手必败,否则先手必胜。


      if(x > y)
       swap(x, y);
      int c = floor((y - x) * (sqrt(5) + 1) / 2);
      if(c == x)
      cout<<0<<endl;
      else
      cout<<1<<endl;
  
 

尼姆博奕:

介绍:有三堆各若干个物品,两个人轮流从某一堆取任意多的物品,规定每次至少取一个,多者不限,最后取

光者得胜.

结论:n堆石子全部做异或运算,结果为0则为必败结果

SG函数:

首先定义mex(minimal excludant)运算,这是施加于一个集合的运算,表示最小的不属于这个集合的非

负整数。例如mex{0,1,2,4}=3mex{2,3,5}=0mex{}=0

对于任意状态 x 定义 SG(x) = mex(F),其中F x 后继状态的SG函数值的集合(就是上述mex中的数

值)。最后返回值(也就是SG(X))为0为必败点,不为零必胜点。

进一步解释一下F,就是题意中给出的可以移动的次数。举个例子来说,一堆石子,每次只能拿13

57个,那么S数组就是1357

假如说是在一个游戏中有多个石子堆该怎么办了。我们只需要把对每个石子堆进行sg函数的调用,将得

到的所有的值进行异或。得出来的结果为0则该情形为必败态。否则为必胜态。


      int sg[MAXN];
      int f[MAXM]; //可以取走的石子个数
      bool Hash[MAXN];
      void getSG(int m)
      {
      memset(sg, 0, sizeof(sg));
      for (int i = 1; i < MAXN; i++) {//枚举石子的个数
      memset(Hash, false, sizeof(Hash));
      for (int j = 0; j < m && f[j] <= i; j++)
       Hash[sg[i-f[j]]] = true;//枚举每次拿走的个数并标记
      for (int j = 0; j < MAXN; j++) {
      if (!Hash[j]) {
       sg[i] = j; //找到这个F[](该状态可以达到的状态)中不存在的最小的数
      break;
       }
       }
       }
      }
      //例题:hdu1847
      int main()
      {
      int n, num = 1;
      for (int i = 0; i < MAXM; num <<= 1, i++)
       f[i] = num;//这里的F数组就是可以移动的步数,每次都是2的幂次
       getSG(MAXM);
      while (cin >> n)
       {
      if (sg[n])
      cout << "Kiki" << endl;
      else
      cout << "Cici" << endl;
       }
      return 0;
      }
  
 

 

 

文章来源: fantianzuo.blog.csdn.net,作者:兔老大RabbitMQ,版权归原作者所有,如需转载,请联系作者。

原文链接:fantianzuo.blog.csdn.net/article/details/102688773

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。