巴什博弈巴什博弈
nim游戏
A与B轮流取石子,有n颗石子,每次取1~3个。取走最后一颗石子的人胜利。
A,B均采用最优策略
当n为0,4, 8, 12…时,B胜利。其他情况,A胜利。
当n为0时,A取不出石子,A输
当n为4时,A取1~3,B取4-numA, A取不出,A输
…
B每次取(numB) 只需要保证与上一次A取的(numA) 相加为4 numA + numB = 4
其他情况
如n为5
A取1, 接下来B取numB,A取4-numB,则B取不出
…
A第一次取n%(m+1), 接下来重复取成4…
总结:
当n%(m+1) == 0 时, B赢,其他A赢。
博弈论当中的一些概念的介绍
必胜点:N点
必败点:P点 (所有状态均是基于先手分析)
博弈论原理
1、若面临末状态者为获胜则末状态为胜态否则末状态为必败态。
2、一个局面是胜态的充要条件是该局面进行某种决策后会成为必败态。
3、一个局面是必败态的充要条件是该局面无论进行何种决策均会成为胜态
nim游戏: 有若干堆石子,每堆石子的数量都是有限的,合法的移动是“选择一堆石子并拿走若干颗(不能不拿)”,如果轮到某个人时所有的石子堆都已经被拿空了,则判负
这种类型的游戏 称为“Impartial Combinatorial Games”简称ICG。
以nim游戏为例: 取石子为1~m, m为3
0,4,8…等点为必败态P, 其他点为必胜态N
0是终止状态,为必败态P
0,4,8等点的后一步next一定是必胜态N 如4只能转化为5,6,7,均为必胜态
nim游戏的升级1:一堆的nim游戏
假如我们取得石子的范围不是1~m, 而是任意的数,应该怎么做呢?
题目:Alice和Bob在玩这样一个游戏:给定k个数字a1,a2…ak。一开始,有x个石子,Alice和Bob轮流取石子。每次所取石子的个数一定要在a1-ak 中。Alice先取。取走最后一个石子的一方获胜。当双方都采取最优策略时,谁会获胜?题目假定a1~ak中一定有1.
输入有 k, A[], x
A[i] 是可以取石头的数量,A[0] ~ A[k],k种选择
x是石头的数量
利用动态规划, 按照j从小到大的顺序计算必胜态,必败态。 判断必胜态和必败态是胜败游戏的基础。
int x, k, A[MaxN]; // 输入
bool win[MaxN + 5];
/* 根据此题, 再给一遍博弈的原理
1. j = 0 是终态,是必败态
2. 对于 **某个** i (0 ~ k -1), j - A[i] 是必败态的话, j就是必胜态。
(当前有j个石子,只要取走A[i]个,对手就输。他们都是聪明人。。。)
即有一个选择能赢,他就会选择这个能赢的选项。所以是必胜态。
3. 对于 **任意** i (0 ~ k-1), j - A[i]是必胜态的话, j就是必败态。
(当前有j个石子,无论怎么取A[i], 都是对方赢,那么现在这个状态就是必败态)
*/
void solve() {
win[0] = false; //0是终态,即必败态
for(int j = 1; j <= x; j++) {
win[j] = false;
for(int i = 0; i < k; i++) {
win[j] |= A[i] <= j && !win[j-A[i]];
//在j中拿A[i]个,所以A[i] <= j;
// A[0] ~ A[k] 每个j-A[i] 都是必胜态(对方赢)
则j是必败态, 有一个j-A[i]是必败态(自己赢)那么就是必胜态
// 为什么使用’|‘呢,循环0~k-1, win[j]的值会改变,所以考虑win[j]
}
}
if(win[x]) puts("Alice") ; // x个石子时
else puts("Bob");
}
之后会再写一篇有关sg函数的。