基础博弈论(巴什博弈、威佐夫博弈、尼姆博弈)

基础博弈论(巴什博弈、威佐夫博弈、尼姆博弈)

先给出三大博弈的定义和基本做法。

巴什博弈:只有一堆共n个石子,两人轮流取,最少取一个,最多取m个,最先取光石子的人赢。 做法:求n%(m+1),如果等于0先手必输,不等于0则先手必赢。

威佐夫博弈:有两堆各x,y个石子,两人轮流从某一堆或同时从两堆中取同样多的石子,规定每次至少取一个,多者不限,最先取光石子的人赢。 做法:若两堆物品的初始值为(x,y),且x< y,记w=(int)((sqrt(5.0)+1.0)/2.0∗(y-x));如果w=x则先手必输,w!=x则先手必胜。

尼姆博弈:有n堆石子(可假设分别为a[1]~a[n]个石子),两人轮流从某一堆取任意多的石子,规定每次至少取一个,多者不限,最先取光石子的人赢。 做法:将所有堆的石子异或起来,如果等于0则先手必输,不等于0则先手必赢。

其他概念:先手必输为P-position,先手必赢为N-position

HDU2147 巴什博弈 博弈论:组合博弈 必败点(P点) :前一个选手(Previous player)将取胜的位置称为必败点。 必胜点(N点) :下一个选手(Next player)将取胜的位置称为必胜点。 现在关于P,N的求解有三个规则 (1):最终态都是P (2):按照游戏规则,到达当前态的前态都是N的话,当前态是P (3):按照游戏规则,到达当前态的前态至少有一个P的话,当前态是N hdu 1846 Brave Game 巴什博弈模板题。 如果n%(m+1)不为0可以先选n%(m+1),之后每次通过对方选的个数X选m+1-X个保证取到最后一个,此时先手必胜,相反后手可以控制这个过程所以后手必胜。

#include

using namespace std;

int main()

{

int n,m,t;

cin>>t;

while(t--)

{

cin>>n>>m;

if(n%(m+1)==0)printf("second\n");

else printf("first\n");

}

return 0;

}

poj 1067 取石子游戏 威佐夫博弈模板题

#include

#include

#include

using namespace std;

int main()

{

int x,y,w;

ios::sync_with_stdio(false);

while(cin>>x>>y)

{

w=(int)((sqrt(5.0)+1.0)/2.0*fabs(y-x));

if(w==(min(x,y)))printf("0\n");

else printf("1\n");

}

return 0;

}

poj 2234 Matches Game 尼姆博弈模板题

#include

#include

using namespace std;

int main()

{

int m,x,ans;

while(cin>>m)

{

ans=0;

while(m--)

{cin>>x;ans=ans^x;}

if(ans==0)printf("No\n");//所有石子异或为0,先手必输

else printf("Yes\n");

}

return 0;

}

poj 2975 Nim 尼姆博弈。 给定nim游戏的一种局面,你是A,对手是B,问你现在这一步有多少种取法使得你进入必胜态。 先求出原状态下所有石子的异或,设为tmp。判断tmp,如果tmp=0,你开始取石子,相当于你是先手,必输,即获胜的方法数为0,直接输出0即可。 如果tmp!=0,那么在你取了之后,就是B取,可以看成你取了石子(必须至少取一个)改变状态后,才正式开始游戏,这时可以把B看作先手,B开始在你取了石子之后的新状态下开始取。要使在你取了石子后的新状态下,作为先手的B必输,也就是要上一步你取了石子之后,所有石子异或为0,此时B必输,A必赢。 遍历a[i],上一步你只能选择一堆石子a[i]取走任意个石子,除a[i]以外的所有石子异或 tmp^a[i] 不变。要在a[i]中取走任意个石子后B必输,也就是要保证上一步你取了石子之后所有石子异或为0,也就是要在a[i]中取任意个石子后剩下的数量为tmp^a[i],那么只要 tmp^a[i]

#include

#include

using namespace std;

int main()

{

int n,i,tmp,cnt,a[1001];

ios::sync_with_stdio(false);

while(cin>>n&&n)

{

tmp=cnt=0;

for(i=1;i<=n;i++)

{cin>>a[i];tmp=tmp^a[i];}

if(tmp==0){printf("0\n");continue;}//tmp=0说明在你取石子之前所有石子异或为0,此状态先手必输,这时你是先手,必输

for(i=1;i<=n;i++)

{if((tmp^a[i])

//if(tmp^a[i]

printf("%d\n",cnt);

}

return 0;

}

poj 2484 A Funny Game 博弈,从进入对称状态入手。 当n<=2时,显然A必胜;当n>=3时,A先手取走一个或两个硬币后,由于硬币组成的环被截断,把环拉直,相当于环被切断后变成了"一条绳子",把"绳子"看成一段序列,那么B则根据这段序列长的奇偶性取出序列最中间的一个或两个硬币,从而把"这条绳子"再切成"两条对称的绳子",这时进入了对称状态,A开始取,由于被切断后的"两条绳子"对称,那么以后的每一步,B只要模仿A取硬币的方式,A取几个硬币,B就可以在对称位置上取几个硬币,这样就可以保证B总会取到最后一个硬币,B必胜。实际上,进入对称状态,就相当于有两堆一样多的石子,A先手开始取,根据尼姆博弈,两堆石子异或为0(因为两堆石子个数一样),所以A必败。

#include

#include

using namespace std;

int main()

{

int n;

while(cin>>n&&n)

{

if(n<=2)printf("Alice\n");

else printf("Bob\n");

}

return 0;

}

参考资料: 尼姆博弈 https://blog.csdn.net/k_koris/article/details/81743806

相关推荐

如何托管服务器
365bet手机娱乐

如何托管服务器

⏱️ 07-08 👁️ 366
你以为是懒,其实已经过度疲劳的 9 种表现
Bet体育365提款流水

你以为是懒,其实已经过度疲劳的 9 种表现

⏱️ 07-03 👁️ 7215
《背包英雄》魔法青蛙托特怎麽樣?背包蛙背景特點
Bet体育365提款流水

《背包英雄》魔法青蛙托特怎麽樣?背包蛙背景特點

⏱️ 06-29 👁️ 2380
新手详细攻略
Bet体育365提款流水

新手详细攻略

⏱️ 06-30 👁️ 1777
港股通交易股票范围详解:哪些股票可以买卖?
Bet体育365提款流水

港股通交易股票范围详解:哪些股票可以买卖?

⏱️ 06-29 👁️ 5199
根号2分之1为什么等于2分之根号2看不懂 的 说点我懂的