博弈论总结

对此博文的简述:大牛博客

(一)巴什博奕(Bash Game):只有一堆n个物品,两个人轮流从这堆物品中取物,规
定每次至少取一个,最多取m个。最后取光者得胜。

总结设n=k*(m+1)+s,如果s==0,则先手输,s!=0,则先手赢

代码:

int Bash_Game(int n,int m){//判断先手输赢(1为赢) 
	if(n%(m+1)) return 1;
	return 0;
}
(二)威佐夫博奕(Wythoff Game):有两堆各若干个物品,两个人轮流从某一堆或同
时从两堆中取同样多的物品,规定每次至少取一个,多者不限,最后取光者得胜。

总结:分析到此已经很明显,判断谁个能够胜利看是否是奇异矩阵就行了,如果是奇异矩阵,则后取者胜利,如果是非奇异矩阵,则先取者得胜!在判断是不是咸佐夫博弈的奇异局势的时候,比如两个数a,b,则可以首先交换是a<b,然后记i=b-a,如果是奇异局势,则必有m=floor(i*(1+sqrt(5.0))/2),并且b=m+i,否则比不是奇异局势!

代码:

int Wythoff_Game(int a,int b){
	if(a>b) swap(a,b);//交换a,b 
	int m=(int)(b-a)*(1+sqrt(5.0))/2;
	if(m==a) return 0;
	return 1;
}

(三)尼姆博奕(Nimm Game)有三堆各若干个物品,两个人轮流从某一堆取任意多的
物品,规定每次至少取一个,多者不限,最后取光者得胜。

总结:面对奇异局势,先取者必定输,如果是非奇异局势,则先取者赢!如果一个局势(a,b,c有a(+)b(+)c==0,则是奇异局势,如果不是,则不是奇异局势!

int Nimm_Game(int n){)//假设n个数存在数组arr[]中,有必胜策略返回1
	int falg=0;
	for(int i=0;i<n;i++)
	flag^=arr[i];
	return flag;
}
(四)SG值求法

有n堆石子,每次从一堆石子中取a到b颗,或者不连续的颗数,但不能不取

判断获胜情况用SG值法。

(HDU1847)代码:

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
const int N = 1010;
int sg[N],f[11];
int vis[N];
void getSG(int n){
	memset(sg,0,sizeof(sg));
	for(int i=1;i<=n;i++){
		memset(vis,0,sizeof(vis));
		for(int j=0;f[j]<=i;j++)
		vis[sg[i-f[j]]]=1;
		for(int j=0;j<=n;j++){
			if(!vis[j]){
				sg[i]=j;
				break;
			}
		}
	}
}
int main(){
	int n;
	for(int i=0;i<=10;i++) f[i]=(1<<i);
	getSG(1000);
	while(scanf("%d",&n)!=EOF&&n){
		if(sg[n]) printf("Kiki\n"); //先手胜 
		else printf("Cici\n");
	}
	return 0;
}
(五)斐波那契博弈
有一堆个数为 n 的石子,游戏双方轮流取石子,满足:
1. 先手不能在第一次把所有的石子取完;
2. 之后每次可以取的石子数介于1到对手刚取的石子数的2倍之间(包含1和对手刚取的石子数的2倍)。

约定取走最后一个石子的人为赢家,求必败态。

当石子数n为斐波那契数时先手输;

例如:HDU2516



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值