首页 > 编程语言 >三个博弈-巴什博奕、威佐夫博弈、尼姆博弈。acm博弈算法笔记HDU 2149,1850,1527

三个博弈-巴什博奕、威佐夫博弈、尼姆博弈。acm博弈算法笔记HDU 2149,1850,1527

时间:2023-06-02 18:36:04浏览次数:158  
标签:HDU 博弈 puts int 奇异 博奕 局势 必输


博弈论

(一)、acm博弈基础算法

Bash Game,Nim Game和Wythoff Game(即 巴什博奕、尼姆博弈、威佐夫博弈)



Bash    Game:   同余理论

Nim      Game:  异或理论

Wythoff Game:  黄金分割

(二)、三个博弈。

1、巴什博奕。

只有一堆n个物品,两个人轮流从这堆物品中取物,

 规定每次至少取一个,最多取m个。最后取光者得胜。

如果n=m+1,那么由于一次最多只能取m个,

所以,无论先取者拿走多少个,后取者都能够一次拿走剩余的物品,后者取胜。

只要保持给对手留下(m+1)的倍数,就能最后获胜.

while(~scanf("%d%d",&n,&m)) { if(n%(m+1)==0)//必输 puts("lose"); else puts("win"); }

巴什博奕练习题HDU2149

代码:

//HDU2149巴什博奕
#include<stdio.h>
int main()
{
	int m,n;//土地价值m,每次最多取n个 
	while(~scanf("%d%d",&m,&n))
	{
		if(m%(n+1)==0)//必输 
			puts("none");
		else
		{//要给对手留下奇异局势(必输局势) 
			int flag=1;
			for(int i=1;i<=n;i++)//枚举
			{
				int mk=m-i<0? 0:m-i;
				if(mk%(n+1)==0)//对手面对奇异局势
				{
					if(flag)
						printf("%d",i),flag=0;
					else
						printf(" %d",i); 
				}
			}
			puts("");
		}
	}
	return 0;
 }

2、尼姆博弈


有三堆各若干个物品,两个人轮流从某一堆取任意多的物品,

规定每次至少取一个,多者不限,最后取光者得胜。

尼姆博弈说的是三堆,但是他的方法却可以推广到任意堆。


尼姆博弈我只会用它的公式,至于原理,,搞不了


即,把所有堆的数量亦或起来,若为0,则先手必输


还要知道一个常识:a, b, a ^ b 三个数之间,两两亦或可得第三个数


分析:

存在一些奇异局势,会使得先手必输,如下面的情况(三堆时)

(0,0,0),(0,n,n)


只要面对这种局势,必输。


任何奇异局势(a,b,c)都有a(+)b(+)c =0。


获胜策略: 所以从一个非奇异局势向一个奇异局势转换的方式可以是:



1)使 a = c(+)b

2)使 b = a(+)c

3)使 c = a(+)b

(14,21,39),14(+)21=27,39-27=12,

所以从39中拿走12个物体即可达到奇异局势(14,21,27)。




尼姆博弈练习题:HDU1850


分析:该题在求得先手是否有必赢策略的基础上,若能赢,输出方案数。


假如每一堆都可以取,取了之后必胜,方案数最多最多等于m(堆数)


看上面的获胜策略,想要留给对手奇异局势,就必须在某一堆取出一些,


使剩下的局势成为奇异局势。


假如我取第c堆想赢,就要保证c的数量大于其他堆的异或结果,才够减


等于不行,等于的话相当于把第c堆取完,


那么其余堆的总亦或不为0,这就给了对手有必赢策略的机会


代码:


3、威佐夫博弈

有两堆各若干个物品,两个人轮流从某一堆或同时从两堆中取同样多的物品,

规定每次至少取一个,多者不限,最后取光者得胜。

分析:

对于给出的两堆石子,记为a个和b个(a<=b),(a,b)。

存在一些特殊情况,当你面对下面一些情况时,必输。

(0,0)、(1,2)、(3,5)、(4,7)、(6,10)、(8,13)、(9,15)。

先看(0,0),若你目前面对这个局势,说明你的对手抢先一步赢了。

再看(1,2),不管你怎么取,你取完后,剩下只可能是(0,1)(0,2)(1,1),对手就会赢

上面的情况称为奇异局势(即 必输)。可以通过下面的公式得到这些奇异局势

a = [ k * eqa ]  ([ ] 代表取整数部分)

b = a + k

其中epa = (1+√5)/2= 1.618033 = (1+sqrt(5.0))/2.0 

可以用这个通项公式打表:

#include<stdio.h>
#include<math.h>
const int N=1000;
const double eqa=(1+sqrt(5.0))/2.0;
int a[N],b[N];
void makelose()
{
	for(int k=0;k<N;k++)
	{
		a[k]=(int)(k*eqa);
		b[k]=a[k]+k;
	}
}


也可以判断任意给出的(a,b)是不是奇异局势

scanf("%d%d",&a,&b); 
	if(a>b)
	{
		a=a^b;
		b=a^b;
		a=a^b;
	}
	int k=b-a;
	if(a==(int)(k*eqa))
		puts("0");//是奇异局势,必败
	else
		puts("1");
#include<stdio.h>
int main()
{
	int m;
	int a[10000];
	while(scanf("%d",&m),m)
	{
		int ans=0;
		for(int i=0;i<m;i++)
		{
			scanf("%d",&a[i]);
			ans=ans^a[i];
		}
		if(ans==0)
			puts("0");//输
		else
		{
			int count=0;
			for(int i=0;i<m;i++)
			{
				if(a[i]-(ans^a[i])>0)//ans^a[i]得到的是除a[i]外所有堆的亦或结果 
					count++;
			}
			printf("%d\n",count);
		}
	}
	return 0;
}


威佐夫博弈练习题 HDU1527

取石子游戏

AC代码:

#include<stdio.h>
#include<math.h>
const double eqa=(1+sqrt(5.0))/2.0;
int main()
{
	int a,b;
	while(~scanf("%d%d",&a,&b))
	{
		if(a>b)
		{
			a=a^b;
			b=a^b;
			a=a^b;
		}
		int k=b-a;
		if(a==(int)(k*eqa))
			puts("0");//遇到奇异局势,必败
		else
			puts("1");
	}
	return 0;
}







标签:HDU,博弈,puts,int,奇异,博奕,局势,必输
From: https://blog.51cto.com/u_16125110/6404535

相关文章

  • 树状数组讲解与例题 杭电HDU1166,HDU1556,HDU2689
    树状数组的总结树状数组很巧妙地解决了数列的求和与查找,速度很快。树状数组,它改变数列中某一位,或者求某个区间的和,时间复杂度是O(logN);效率大为改善。下面的图片很好的演示了树状数组的存储原理。(图片来自网络)观察图片,会发现:数组c的每一个元素都管辖着一定范围内的数组a元素的和,比如C......
  • HDU 5542 The Battle of Chibi(树状数组+dp)
    TheBattleofChibiTimeLimit:6000/4000MS(Java/Others)    MemoryLimit:65535/65535K(Java/Others)TotalSubmission(s):1749    AcceptedSubmission(s):621ProblemDescriptionCaoCaomadeupabigarmyandwasgoingtoinvadethewholeSou......
  • ICPC2015(沈阳)HDU5521 建图技巧+最短路
    MeetingTimeLimit:12000/6000MS(Java/Others)  MemoryLimit:262144/262144K(Java/Others)TotalSubmission(s):3533  AcceptedSubmission(s):1136ProblemDescriptionBessieandherfriendElsiedecidetohaveameeting.However,afterFarmerJohndecor......
  • 【学习笔记】博弈论 ---- 非偏博弈
    博弈论入门前言:本篇按照Qingyu在省集讲的加入我这个萌新的萌新理解而成。听了Qingyu的博弈论讲解,感觉我之前学过的博弈就是冰山一角。由于有一些东西没听懂,就主要写写我听懂的部分,没懂得以后再说吧。所以这篇只是一个入门,关于博弈的一些习题可能会咕咕咕。平等博弈(非偏......
  • HDU2227(非降子序列的个数)
    题目:http://acm.hdu.edu.cn/showproblem.php?pid=2227题意:给定一个长度为n(n<=100000)的整数序列,求其中的非降子序列的个数。分析:如果n的值比较小,那么就是一个纯粹的dp题。设dp[i]表示以a[i]为结尾非降子序列的个数,其状态转移方程为:      可以看出,这样做的时间复杂度是......
  • HDU4372(第一类斯特林数)
    题目:CounttheBuildings题意:N座高楼,高度均不同且为1~N中的数,从前向后看能看到F个,从后向前看能看到B个,问有多少种可能的排列数。0<N,F,B<=2000首先我们知道一个结论:n的环排列的个数与n-1个元素的排列的个数相等,因为P(n,n)/n=(n-1)!。可以肯定,无论从最左边还是从最右边看,......
  • HDU4633(Polya计数)
    题目:Who'sAuntZhang#include<iostream>#include<string.h>#include<stdio.h>usingnamespacestd;typedeflonglongLL;constLLMOD=10007;LLquick_mod(LLa,LLb){LLans=1;a%=MOD;while(b){if(b&1......
  • HDU4382(特殊的矩阵连乘)
    题目:HarryPotterandCyberSequenceGenerator题意,有两个容器C1,C2,初始的时候C1中有一个数的值为V,给你K个操作,每次都重复这K个操作N遍,最后问你C2中的数是   多少。N<=10^100。1:循环操作的次数巨大,敏感的想到这是矩阵连乘的题目。2:K个操作可以得出一个矩阵,N个K操作就是这个......
  • HDU1524(博弈--有向无环图SG函数)
    题目:http://acm.hdu.edu.cn/showproblem.php?pid=1524题意:在一个有向无环图上有n个顶点,每一个顶点都只有一个棋子,有两个人,每次根据这个图只能将任意一颗棋子移动一步,如果到某一步玩家不能移动时,那么这个人就输.分析:本题是最典型的有向无环图的博弈,利用dfs把所有顶点的SG值......
  • HDU3662(求三维凸包表面的多边形个数,表面三角形个数,体积,表面积,凸包重心,凸包中点到面
    题目:3DConvexHull题意:给定空间中的n个点,求这n个点形成的凸包的表面的多边形个数。增量法求解:首先任选4个点形成的一个四面体,然后每次新加一个点,分两种情况:1>在凸包内,则可以跳过2>在凸包外,找到从这个点可以"看见"的面S(看不看得见可以用法向量,看点是否在面外侧),删除这些......