目录
一,博弈的分类
1,分类理念
正常来讲,科学中的很多分类问题都是交叉分类,博弈也是。
但是如果考虑所有组合,就太多太乱了,所以我们尽量选择一个常规的方式,按照接近树形分类来完成所有博弈问题的分类。
比如,我看了一堆分类方法之后,觉得用博弈者之间是否有合作关系来作为顶层分类,就比较符合常规思维。
2,合作博弈、非合作博弈
从博弈者之间是否有合作关系的角度,博弈可以分为合作博弈(Cooperative Game)和非合作博弈(Non-Cooperative Game)。
当然,还有特殊的单人博弈问题。
3,完全信息、非完全信息
多人博弈中,一个人知道其他人的所有相关信息,称为完成信息博弈。反之则是非完全信息。
4,静态博弈、动态博弈
静态博弈指的是所有人同时决策,动态博弈指的是回合制轮流决策。
5,所有博弈类型
结合上面3个分类标准,可以分为6大博弈类型:
单人博弈、多人合作博弈、多人非合作完全信息静态博弈、多人非合作完全信息动态博弈、多人非合作非完全信息静态博弈、多人非合作非完全信息动态博弈。
6,博弈的标准式
(1)博弈者
博弈者用下标1,2,3...n表示
(2)战略集
每个博弈者都有一个战略集S,集合中的每个元素代表该博弈者的一种选择。
战略集也叫战略空间、策略集、策略空间。
其中的每个选择可以叫做一个策略。
(3)收益函数
每个博弈者都有一个收益函数u,自变量是n个博弈者的选择,应变量是个数值。
(4)博弈的标准式
7,纯策略、混合策略
纯策略就是在策略空间中选择一个具体的策略。
混合策略就是给所有的策略分配一个具体的概率,按照概率决定实际选出的策略。
PS:纯策略也属于混合策略中的一种。
二,单人博弈
如独立钻石棋
三,多人合作博弈
1,多人合作博弈的例子
我们可以用3个程序员合作写代码作为一例子,一个项目有500行需要写。以下是一个人单独做,两个人合作,以及三个人合作产生的结果。其中C可以看作程序员鼓励师,当一个人做的时候结果不多,但是合作时可以大大提高两人的合作成果。
合作 | 价值 |
---|---|
A | 100 |
B | 125 |
C | 50 |
AB | 270 |
BC | 350 |
AC | 375 |
ABC | 500 |
2,夏普利值
这是一种衡量在多人合作中,每个成员贡献值的方法。
计算方法就是枚举n个人的所有可能的n!种顺序,对于每种顺序,每个人加入前后的价值差就是这个人在这个顺序中的贡献。一个人在所有顺序中的贡献的均值,就是夏普利值。
上面的例子中,3个人合作的话有6种可能
顺序 | A的贡献 | B的贡献 | C的贡献 |
---|---|---|---|
ABC | 100 | 170 | 230 |
ACB | 100 | 125 | 275 |
BAC | 145 | 125 | 230 |
BCA | 150 | 125 | 225 |
CAB | 325 | 125 | 50 |
CBA | 150 | 300 | 50 |
由此我们可以计算每个人的夏普利值,发现
人 | 夏普利值 |
---|---|
A | 970/6 |
B | 970/6 |
C | 1060/6 |
虽然A和B单独一人对于整个项目的贡献是大大多于C的,但是C在合作中对于整体的贡献是多于A和B的。
四,多人非合作博弈
1,纳什均衡
对于四种不同的博弈,有四种不同的纳什均衡。
2,完全信息静态博弈
有限的完全信息静态博弈一定存在混合策略纳什均衡。
有限指:有限的玩家,每个玩家都有有限种纯策略。
(1)囚徒困境、纯策略纳什均衡
囚徒困境是典型的纯策略纳什均衡。
囚徒困境:
两个嫌疑人被捕,但是警方并无充足证据证明他们犯罪,因此希望他们至少有一人可以主动招认,于是将他们关到不同的询问室,并对他们说明不同决定所带来的后果。为了贯彻落实“坦白从宽,抗拒从严”的政策,如果一方招认而另一方拒不配合,招认的一方将马上得到释放,而另一方将被判入狱9个月;如果双方都不招认,则两人均被从轻判处,入狱1个月;如果双方均招认,则两人均被判处6个月。请问两个囚徒该如何选择呢?
囚徒们所面临的问题可用下列矩阵表示,其中左边的数字代表囚徒1的收益,右边的数字代表囚徒2的收益。
囚徒2 | |||
沉默 | 招认 | ||
囚徒1 | 沉默 | -1,-1 | -9,0 |
招认 | 0,-9 | -6,-6 |
分析:
如果2个囚徒可以交流,那肯定是都沉默,那就是合作博弈了。现在是不能交流,所以是非合作博弈。
最终的结果也很显然,2个囚徒都会招认,因为无论对方选什么,自己招认都比不招认好。
(2)石头剪刀布、混合策略纳什均衡
石头剪刀布的策略很简单,随机出。
3,多人非合作完全信息动态博弈
如公开游戏、有向有环图游戏。
绝大部分棋类要么是公开游戏里面的有向无环图游戏(无平局),要么是有向有环图游戏(有平局)。
对应的均衡是子博弈精炼纳什均衡。
4,多人非合作非完全信息静态博弈
对应的均衡是贝叶斯纳什均衡
5,多人非合作非完全信息动态博弈
如军棋。
大部分牌类游戏、大部分麻将游戏也都属于这一类。
对应的均衡是精炼贝叶斯纳什均衡。
力扣 375. 猜数字大小 II
我们正在玩一个猜数游戏,游戏规则如下:
- 我从
1
到n
之间选择一个数字。 - 你来猜我选了哪个数字。
- 如果你猜到正确的数字,就会 赢得游戏 。
- 如果你猜错了,那么我会告诉你,我选的数字比你的 更大或者更小 ,并且你需要继续猜数。
- 每当你猜了数字
x
并且猜错了的时候,你需要支付金额为x
的现金。如果你花光了钱,就会 输掉游戏 。
给你一个特定的数字 n
,返回能够 确保你获胜 的最小现金数,不管我选择那个数字 。
示例 1:
输入:n = 10 输出:16 解释:制胜策略如下: - 数字范围是 [1,10] 。你先猜测数字为 7 。 - 如果这是我选中的数字,你的总费用为 $0 。否则,你需要支付 $7 。 - 如果我的数字更大,则下一步需要猜测的数字范围是 [8,10] 。你可以猜测数字为 9 。 - 如果这是我选中的数字,你的总费用为 $7 。否则,你需要支付 $9 。 - 如果我的数字更大,那么这个数字一定是 10 。你猜测数字为 10 并赢得游戏,总费用为 $7 + $9 = $16 。 - 如果我的数字更小,那么这个数字一定是 8 。你猜测数字为 8 并赢得游戏,总费用为 $7 + $9 = $16 。 - 如果我的数字更小,则下一步需要猜测的数字范围是 [1,6] 。你可以猜测数字为 3 。 - 如果这是我选中的数字,你的总费用为 $7 。否则,你需要支付 $3 。 - 如果我的数字更大,则下一步需要猜测的数字范围是 [4,6] 。你可以猜测数字为 5 。 - 如果这是我选中的数字,你的总费用为 $7 + $3 = $10 。否则,你需要支付 $5 。 - 如果我的数字更大,那么这个数字一定是 6 。你猜测数字为 6 并赢得游戏,总费用为 $7 + $3 + $5 = $15 。 - 如果我的数字更小,那么这个数字一定是 4 。你猜测数字为 4 并赢得游戏,总费用为 $7 + $3 + $5 = $15 。 - 如果我的数字更小,则下一步需要猜测的数字范围是 [1,2] 。你可以猜测数字为 1 。 - 如果这是我选中的数字,你的总费用为 $7 + $3 = $10 。否则,你需要支付 $1 。 - 如果我的数字更大,那么这个数字一定是 2 。你猜测数字为 2 并赢得游戏,总费用为 $7 + $3 + $1 = $11 。 在最糟糕的情况下,你需要支付 $16 。因此,你只需要 $16 就可以确保自己赢得游戏。
示例 2:
输入:n = 1 输出:0 解释:只有一个可能的数字,所以你可以直接猜 1 并赢得游戏,无需支付任何费用。
示例 3:
输入:n = 2 输出:1 解释:有两个可能的数字 1 和 2 。 - 你可以先猜 1 。 - 如果这是我选中的数字,你的总费用为 $0 。否则,你需要支付 $1 。 - 如果我的数字更大,那么这个数字一定是 2 。你猜测数字为 2 并赢得游戏,总费用为 $1 。 最糟糕的情况下,你需要支付 $1 。
提示:
1 <= n <= 200
本来想用一维DP:
class Solution {
public:
map<int, int>m;
int g(int n) {
if (n < 2)return 0;
return g(n / 2) + 1;
}
int getMoneyAmount(int n) {
if (n < 2 || m[n])return m[n];
m[n] = INT_MAX;
for (int k = 1; k <= n; k++) {
m[n] = min(m[n], k + max(getMoneyAmount(k - 1),getMoneyAmount(n - k) + k * g(n - k)));
}
return m[n];
}
};
提交发现答案错误,应该是递推式不对,果断改成二维DP:
class Solution {
public:
map<int, map<int,int>>m;
int getMoneyAmount(int s, int n) {
if (n <= s || m[s][n])return m[s][n];
int ans = INT_MAX;
for (int k = s; k <= n; k++) {
ans = min(ans, k + max(getMoneyAmount(s, k - 1),getMoneyAmount(k+1,n)));
}
return m[s][n]=ans;
}
int getMoneyAmount(int n) {
return getMoneyAmount(1, n);
}
};
这次答案应该完全正确了,可惜超时了。
于是我果断硬编码:
class Solution {
public:
int ans[200] = {
0,1,2,4,6,8,10,12,14,16,18,21,24,27,30,34,38,42,46,49,52,55,58,61,64,67,70,73,76,79,82,86,
90,94,98,102,106,110,114,119,124,129,134,139,144,149,154,160,166,172,178,182,186,190,194,
198,202,206,210,214,218,222,226,230,234,238,242,246,250,254,258,262,266,270,274,278,282,
286,290,295,300,305,310,315,320,325,330,335,340,345,350,355,360,365,370,376,382,388,394,400,
406,412,418,424,430,436,442,448,454,460,466,473,480,487,494,501,508,515,522,529,536,543,550,
555,560,565,570,575,580,585,590,595,600,605,610,615,620,625,630,635,640,645,650,655,660,666,
674,680,686,692,698,703,708,713,718,723,728,733,738,743,748,753,758,763,768,773,778,783,788,
793,798,803,808,813,818,823,828,833,838,843,848,853,858,863,868,873,878,883,888,893,898,
904,910,916,922,928,934,940,946,952
};
int getMoneyAmount(int n) {
return ans[n - 1];
}
};
五,博弈趣题
递归方法
配对法
平衡法
数学归纳法
反证法