博弈论

理论知识

博弈论又被称为对策论(Game Theory)既是现代数学的一个新分支,也是运筹学的一个重要学科。
博弈论主要研究公式化了的激励结构间的相互作用。是研究具有斗争或竞争性质现象的数学理论和方法。 博弈论考虑游戏中的个体的预测行为和实际行为,并研究它们的优化策略。生物学家使用博弈理论来理解和预测进化论的某些结果。
博弈论已经成为经济学的标准分析工具之一。在生物学、经济学、国际关系、计算机科学、政治学、军事战略和其他很多学科都有广泛的应用。
基本概念中包括局中人、行动、信息、策略、收益、均衡和结果等。其中局中人、策略和收益是最基本要素。局中人、行动和结果被统称为博弈规则。

相关的博弈

一,巴什博弈

题目描述
Alice和Bob玩取石子游戏。他们的游戏是这样的:总共有 n 个石头,每个人每次可以取 1 到 m 个石头,不能不取。最后取完的人获胜。现在Alice先取,假设双方都采取最好的策略,告诉你 n 和 m,问他是否能赢,如果能,第一次要取几个。
输入格式
只有一行,两个非负整数 n 和 m。
输出格式
第一行 Yes 或 No,表示Alice是否能赢。如果为 Yes,则有第二行,表示要取几个。
样例输入
100 8
样例输出
Yes
1
数据规模与约定
n,m是longint之内的数

题目分析
因为对方取的石子是个不确定值,以至于我们无法判断结果。所以我们就要通过策略构造确定值。
先手取得石子数我们是可以控制的,所以把两个和在一起看—>我们可以设置一个值sum,表示双方取得石子每次加在一起都是sum,而我们要确定这个sum,使得无论对方取何值,我们都可以构造出sum
当对方取最小值1时,sum最小为2(1+1),最大为1+m 当对方取最大值m时,sum最小值为1+m,最大值为2m
可以把这个看做类似于不等式的东西,那么sum唯一可以取得是1+m (图脑补吧) 所以sum唯一可取值是1+m,也就是两段的唯一交接处了

题目代码

#include<iostream>
#include<cstdio>
using namespace std;
int main(){
	long long n,m;
	scanf("%lld%lld",&n,&m);
	if(n%(m+1)==0) printf("No\n");
	else printf("Yes\n%lld",n%(m+1));
	return 0;
}

二,威佐夫博弈

题目描述
LTL 和清华哥玩取石子游戏。他们的游戏是这样的:有两堆数量为 a 和 b 的石头。游戏开始两个人轮流取石子。游戏规定,每次有两种不同的取法,一是可以在任意的一堆中取走任意多的石子;二是可以在两 堆中同时取走相同数量的石子。最后把石子全部取完者为胜者。现在给出初始的两堆石子的数目,如果轮到 LTL 先取,假设双方都采取最好的策略,问最后 LTL 是胜者还是败者。
输入格式
输入包含若干行(不超过 100,000 行),表示若干种石子的初始情况,其中每一行包含两个非负整数 a 和 b,表示两堆石子的数目,a 和 b 都不大于 1,000。
输出格式
输出对应也有若干行,每行包含一个数字 1 或 0,如果最后你是胜者,则为 1,反之,则为 0。
样例输入
2 1
4 7
8 4
样例输出
0
0
1

题目分析
较为详细的可以参考百度百科
我们来分析一下几个局面

  1. 当石子数为(0,0)时,先手已经没有石子可以取,输
  2. 当石子数为(1,2)时
    1,在第一堆取1个,后手取走第二堆的2个,输
    2,在第二堆取1个,后手在两堆同时取走1个,输
    3,在第二堆取2个,后手在第一堆取走1个,输
    4,在两堆同时取走1个,后手在第二堆取走1个,输
  3. 当石子数位(3,5)时(我并不想证)
  4. 以此类推,可以自己尝试证明一下

所以我们可以发现,以下这几个局面的时候,先手必输
(0,0)、(1,2)、(3,5)、(4,7)、(6,10)、(8,13)、(9,15)、(11,18)、(12,20)等等
通过计算(也不是我算的),当局势(a,b)(我们设置a<b)满足a=(b-a) * 1.618时,先手必输,也就是当前为奇异局势
在实际编程中,我们需要一个更精确的值,也就是a=(b-a) * (sqrt(5)+1) / 2

题目代码

#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
int main()
{
	int a,b,x,k,num;
	num=(1+sqrt(5))/2;
	while(cin>>a>>b)
	{
		if(a<b) {x=a;a=b;b=x;}
		if(b==(int)((a-b)*((1+sqrt(5)))/2)) cout<<0<<endl;
		else cout<<1<<endl;
	}
}

三,尼姆博弈

(我错了我找不到原题)
指的是这样的一个博弈游戏,目前有任意堆石子,每堆石子个数也是任意的,双方轮 流从中取出石子,每一步应取走至少一枚石子;每一步只能从某一堆中取走部分或全部石子,取到最后一枚石子者胜

题目分析

尼姆博弈的方法很简单,即对每一堆石头数进行异或运算,如果最终的结果是0,那么先手必败,否则先手胜

题目代码

#include<iostream>
#include<cstdio>
using namespace std;
typedef long long ll;
int  main()
{
   int n,m,a[105],ans,cnt,i;
   cin>>n>>m;
   ans=0;
   for(i=0;i<n;i++){
       cin>>a[i];
       ans^=a[i];
   }
   if(ans==0)
    cout<<"not win"<<endl;
    else cout<<"win"<<end; 
}

题目拓展
在另一博主上看到的一个拓展,是求如果当前不是奇异局势,那么先手如何选取,让自己胜利的方法数

int cnt=0;
for(i=0;i<n;i++){
     int k=ans^a[i];
     if(k<a[i])//就相当于举得例子中减去一个数
         cnt++;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值