博弈论学习笔记
# 回合制博弈
# 策梅洛定理(Zermelo's theorem)
In game theory, Zermelo's theorem is a theorem about finite two-person games of perfect information (opens new window) in which the players move alternately and in which chance does not affect the decision making process. It says that if the game cannot end in a draw, then one of the two players must have a winning strategy (i.e. force a win). An alternate statement is that for a game meeting all of these conditions except the condition that a draw is not possible, then either the first-player can force a win, or the second-player can force a win, or both players can force a draw
如果满足以下条件
两人(A、B)博弈,交替执子(回合制)
有限回合
信息完备
不受随机性影响
那么,要么玩家A有必胜策略,要么玩家B有必胜策略,要么A、B都有必定平局的策略
如果满足
- 没有平局
那么,任意一方有必胜策略。
# Nim(SG函数)
假设有个石子,在游戏时轮流取走个石子,无法取得石子者败(Nim)。
定义,其中代表从状态可以转移到状态,代表不属于集合的最小非负整数。
那么的为必败状态,的为必胜状态。
容易注意到,函数中只考虑了的状态,那么那些中的可行状态呢?
假设当前状态值为,先手玩家将其转移为。那么根据函数的定义,后手玩家总可以转移到一个新状态,使得,在有限步数的情况下,必胜/必败情况不变(多堆石子时也是如此)
若有多堆石子,可以视为多个游戏,其中每个游戏分别的函数,那么整局游戏的函数则为
简要证明如下:
假设当前的状态为,玩家必须改变某一,则必然使得下一状态(反证法可证)。
假设当前状态,下面将证明必定存在一操作使得下一状态
- 记的二进制最高位位置为
- 在中找到任意一个二进制第位为1的值,记为
- 将第位置0,低位与相同,其余位不变,得到
- 新的状态
这就说明了,最优策略下,的状态必将走向的状态,的状态必将走向的状态。
# NimK
有堆石子,每堆有个。玩家每次可以选择不超过堆石子,并从选中的堆中取出任意数量()的石子;无法取得石子者败。Nim可以看作是NimK的特例()。
设每堆的函数分别为,将的二进制表示按位相加(但不进位,每位分别对2取余)后对取余得到。先手必胜的。
证明如下:
如果,由于选择的堆数不超过,根据的定义,
如果,下面将证明必定存在一种操作使得下一状态
初始时,所有均未被标记,记分别为二进制第位为且被标记的数之个数
- 记的二进制最高位位置为
- 找到任意一个二进制第位为1且未被标记的值
- 将的第位置0,位则根据该位的值,更新,其余位忽略
- 更新后,若,记(第位非零)。如果或(当时,两者至少有一个成立),则可以通过修改已经标记的,使得,置
- 如果经过步骤后,则回到步骤
最终,且选取的堆数
# NimK例题 POJ 2315
AC代码
#include <iostream>
#include <cstring>
#include <cmath>
#define Android ios::sync_with_stdio(false), cin.tie(NULL)
using namespace std;
const double PI = acos(-1);
int n, m, l, r;
int sg[50], bit_cnt[33];
void table(){ // 打表函数
const int len = 50;
int table_sg[len];
bool appear[len];
for(int k=1; k < 10; k++){
cerr << "\n----------\n";
table_sg[0] = 0;
for(int i=1; i<len; i++){
memset(appear, 0, sizeof appear);
for(int j=i-1; j>=0 && i-j<=k; j--)
appear[table_sg[j]] = true;
for(int j=0; j<len; j++) if(!appear[j]){
table_sg[i] = j;
break;
}
}
for(int i=1; i<len; i++) cerr << table_sg[i] << " ";
}
}
string solve(){
memset(bit_cnt, 0, sizeof bit_cnt);
double cir = 2 * PI * r; //
int max_k = l / cir;
for(int i=1; i<=n; i++) {
cin >> sg[i];
sg[i] = ((int)ceil(sg[i] / cir)) % (max_k + 1); // 打表得出SG函数规律
// 由于Pi是无理数(不能写作两整数之比),因此可以把ceil换成+1
}
for(int i=1; i<=n; i++){
for(int j=0; j<31; j++){
if(sg[i] & (1<<j)) bit_cnt[j]++;
}
}
for(int j=0; j<31; j++){
if(bit_cnt[j] % (m + 1) != 0) return "Alice";
}
return "Bob";
}
signed main(){
Android;
while(cin >> n >> m >> l >> r) cout << solve() << '\n';
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
# Anti-Nim
有堆石子,每堆分别有个,每次只能从一堆中取出任意数目的石子,取走最后一个石子者败。
显然对于单个堆,,对于整局游戏,
先手必胜当且仅当:
- 所有都为,且整局的
- 存在,且整局的
注意:我们规定,的局面不一定为必败局面
证明见 贾志豪《组合游戏略述——浅谈SG游戏的若干拓展及变形》
# 其他博弈模型
除了上述模型以外,还有许多博弈模型,如
- Every-SG
- 威佐夫博弈(Wythoff's game)
- Fibonacci Nim
- Staircase Nim
- 非回合制博弈
等等