nim 博弈论

1.排石头游戏

给你一排n个石头,每次只能取一个或两个,求必胜策略
先讨论石头是奇数还是偶数,奇数就从中间拿一个,然后,对手拿几个,你就从与它对应的位置上拿几个。偶数的话就从中间拿2个。

2.巴什博奕(Bash Game)

只有一堆n个物品,两个人轮流从这堆物品中取物,规定每次至少取一个,最多取m个。最后取光者得胜。
n=s+(m+1)*k
先手拿s个,然后对手拿l个,你就拿m+1-l个。

3.威佐夫博奕(Wythoff Game)

有两堆各若干个物品,两个人轮流从某一堆或同时从两堆中取同样多的物品,规定每次至少取一个,多者不限,最后取光者得胜。
这个游戏所包含的数学原理很深,先手必败 ,公式是a=i*(1+sqrt(5))/2(I=0~n);b=a+n;
参考编程之美,里面将原理讲的非常详细。
公式证明就不写了,主要就是证明a,b包含了整个自然数集,并且不重复。1/a+1/b=1。a-b=1。联立方程组,求解。这里要引用一个定理,参考博客https://blog.csdn.net/maththinker/article/details/47757445

这是直接公式求解:
bool nim(int x, int y) {
 double a, b;
 a = (1 + sqrt(5.0)) / 2;
 b = (3 + sqrt(5.0)) / 2;
 if (x == y)return true;
 if (x > y)swap(x, y);
 if (y - x == (long)floor(x*a))return false;
 return true;
}
这是迭代出所以不安全局面:
#include<iostream>
#include<string.h>
#include<sstream>
#include<set>
#include<algorithm>
#include<vector>
#include<map>
#include<queue>
#include<Windows.h>
#include<math.h>
using namespace std;
const int maxn = 100000;
bool nim(int x, int y) {
 if (x == y)return true;//先手必胜,这是安全局面
 if (x > y)swap(x, y);
 if (x == 1 && y == 2)return false; //先手必输,这是不安全局面
 vector<int> A;
 A.push_back(2);
 int n = 1;
 int delta = 1;
 int mp[maxn];
 memset(mp, 0, sizeof(mp));
 mp[2] = 1;
 while (x > n) {
  while (mp[++n]);
  delta++;
  A.push_back(n + delta);
  mp[n + delta] = 1;
 }
 if (x != n || !mp[y])return true;//已知的不安全局面中没有它
 else return false;
}
int main(){
 cout << (nim(6, 10) ? "win" : "lose") << endl;
 system("pause");
 return 0;
}

4.nim堆

有n堆各若干个物品,两个人轮流从某一堆取任意多的物品,规定每次至少取一个,多者不限,最后取光者得胜。
m1 ^ m2 ^ m3 ^ m4…=0表示先手必败
改变一个值肯定使它们异或不为0 。如果一开始不为0,那么就找到这个改变的数使它变为0。

5思考题

在这里插入图片描述
这个思考题就比较有意思了,但是不难,不妨先将1,2,3,4,5,6,7等较小的局面给推出来。
我们可以知道n>1,n=2时,我拿只能拿一个,你就可以拿完,显然是必输局,暂称为N。n=3时,显然也是N局,n=4,显然不是N局,暂称为Y局,为了保证不一开始就输,我只能拿1个,你为了不输也只能拿一个,然后我就能拿完。n=5时显然是必输局势,它只有两种拿法,一种是拿一个,拿完后局势就变成4,也就是你的Y局,拿2个,那就接输了。所有我们不难发现一个规律,将前一个N局势称为Nn-1,(n-Nn-1)*2<Nn-1,让后者不能一次拿光并且你处在N局势,符合这个条件就是Y局势。N局势显然就是不能转换到前一个N局势的数。
主要难点就在于对于状态转换的处理。如何将局势转换成必胜局势,让对手必输。

总结

总的来说,博弈论游戏有很多,也没人能将所有公式都列出来,也不必将所有公式都背下来,关键是如何分析问题,如何设计一个方法来解决它,更深层次就可以推导出它的数学原理。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值