博弈问题

一、必胜策略

规律策略

硬币游戏1

Alice和Bob在玩这样一个游戏。给定k个数字a[1],a[2],…,a[k]。一开始,有x枚硬币,Alice和Bob轮流取硬币。每次所取硬币的枚数一定要在a[1],a[2],…,a[k]当中。Alice先取,取走最后一枚硬币的一方获胜。当双方都采取最优策略时,谁会获胜?题目假定a[1],a[2],…,a[k]中一定有1。

int k,n; //k枚硬币 n个数字
int win[maxn];
void judge(){

	win[0]=0; //轮到自己没硬币,失败
	for (int i=1; i<=k; i++){
		win[i]=0;
		for (int j=0; j<n; j++){
			win[i]|=a[j]<=i && !win[i-a[j]]; //让对手必败,则必胜
		}
	}
	if (win[k]) cout<<"Alice\n";
	else cout<<"Bob\n";
}

A funny game

n枚硬币排成一个圈。Alice和Bob轮流从中取一枚或两枚硬币。取两枚时,所取两枚必须连续。取走之后留下空位,相隔空位的硬币不连续。Alice开始先取,取走最后一枚硬币的一方获胜。当双方都采取最优策略时,谁会获胜?
在这里插入图片描述

无论自己采取什么策略,对手如果采取相同策略,
一定能回到相同情况,那么对手会取完最后一枚硬币,所以必败。
int n;
void solve(){
	if (n<=2) cout<<"Alice\n";
	else cout<<"Bob\n";
}

Euclid’s Game

给定两个整数a和b。Stan和Ollie轮流从较大的数字中减去较小的数字的倍数(正整数倍),并且相减后的结果不能小于零。Stan先手,在自己的回合将其中一个数变为零的一方获胜。当双方都采取最优策略时,谁会获胜?

假设a<b (a>b则交换)
假设b并非a的倍数,则有两种状态:
(1)b-a<a
(2)b-a>a
第二种状态总是必胜,所以从初始状态开始,最先达到第二状态的一方必胜
int a,b;
void solve(){
	bool flag=true;
	while (1){
		if (a>b) swap(a,b);
		
		if (b%a==0) break;
		
		if (b-a>a) break;
		b-=a;
		flag=!flag;
	}
	if (flag) cout<<"Stan wins\n";
	else cout<<"Ollie wins\n";
}

二、Nim Game(尼姆博弈)

Nim

有n堆石子,每堆各有ai颗石子。Alice和Bob轮流从非空的石子堆中取走至少一颗石子。Alice先取,取光所有石子的一方获胜。当双方都采取最优策略时,谁会获胜?

有以下结论成立:
a1 XOR a2 XOR…XOR an ≠ 0 ->先手必胜
a1 XOR a2 XOR…XOR an = 0 ->先手必败
int n,a[maxn];
void solve(){
	int x=0;
	for (int i=0; i<n; i++)
		x^=a[i];
	if (x!=0) cout<<"Alice\n";
	else cout<<"Bob\n";
}

Staircase Nim

在这里插入图片描述
如图所示,排成直线的格子上放有n个棋子。棋子i在左数第pi个格子上。Georgia和Bob轮流选择一个棋子向左移动。每次可以移动至少一格,但是不允许反超其他棋子,也不允许两个棋子在同一格内。无法进行移动操作的一方失败。假设Georgia先进行移动,当双方都采取最优策略时,谁会获胜?

将棋子两两成对当作整体考虑,可以转化为Nim Game

(1)偶数情况下,从前往后两两一对,每队相当于Nim Game中的一堆石子,石子个数相当于两个棋子间的间隔。
注意,当左边棋子向左移动,石子数量增加,和Nim不同,但是右边移动到左边,左边再移动到左边,就回到了原来的状态,所以胜负状态和Nim的胜负状态相同
(2)奇数情况下,将最左边单独一个棋子与left断的间隔作为石子数。

int n,a[maxn];
void solve(){
	if (n%2) a[n++]=0; //奇数时,在最左边添一个棋子 
	sort(a,a+n);
	int x=0;
	for (int i=0; i+1<n; i+=2){
		x^=a[i+1]-a[i]-1;
	}
	if (x==0) cout<<"Bob will win\n";
	else cout<<"Georgia will win\n";
}

三、Grundy数


int grundy(int x){
	集合S={};
	for(j=1:k){
		if(a_j<=x) 将grundy(x-a_j)加到S集合中 
	} 
	return 最小的不属于S的非负整数 
}

Grundy值:除任意一步所能转移到的状态的Grundy值以外的最小非负整数
Nim的XOR结论就转化为:

grundy(x1) XOR grundy(x2) XOR…XOR grundy(xn)
不为0必胜,为0必败

硬币游戏2

给定k个数字a1,a2,…,ak。一开始,有n堆硬币,每堆各有xi枚。Alice和Bob轮流选取一堆硬币,从中取出一些硬币。每次所取硬币枚数一定在ai中。Alice先取,取光的一方获胜。当双方都采取最优策略时,谁会获胜?

int N,K,X[maxn],A[maxk];
int grundy[maxx+1];
void solve(){
	//轮到自己剩0的时必败 
	grundy[0]=0;			
	
	//计算grundy 
	int max_x=*max_element(X,X+N);
	for(int j=1;j<=max_x;j++){
		set<int> s;			
		for(int i=0;i<K;i++){
			if(A[i]<=j) s.insert(grundy[j-A[i]]);
		}
		int g=0;				
		while(s.count(g)!=0) g++;
		grundy[j]=g;
	}	
	int ans=0;
	for(int i=0;i<N;i++) ans^grundy[X[i]];
	
	if(ans!=0)	puts("Alice");
	else puts("Bob");
	
}

Cutting Game

未完待续

四、SG函数及运用

五、更多博弈

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值