阶梯博弈学习笔记

· · 个人记录

众所周知我不会博弈论。

首先给出阶梯博弈的一个基本模型:

现在我们给出结论:

接下来考虑如何感性理解这个结论。

这里要用到博弈题中的一个常用套路——后手模仿先手操作

在这个模型中:

于是我们可以将原问题等效为奇数层上石子的 Nim 游戏。

现在我们先将 a 排序,然后来考虑一些特殊情况。

此时先手必胜。

此时问题变为——先后手轮流操作,不能操作者失败

我们将棋子右移视为中间的空格左移,并将这个问题转化一下:

然后你发现这就是一个阶梯博弈的模型!然后这种情况就解决了。

我们来思考一下到底什么时候我们会关心第 k 个棋子。

k = 2,先后手都一定不会主动将第一个棋子移动到 0,此时我们可以认为 a_1 减去了 1

你发现在其他情况下跟 k = n 是一致的。

然后这道题就做完了。

代码:

#include <iostream>
#include <algorithm>

using namespace std;

int a[1007];

int main(){
    int n, k;
    a[0] = -1;
    while (cin >> n >> k){
        for (int i = 1; i <= n; i++){
            cin >> a[i];
        }
        sort(a + 1, a + n + 1);
        if (k == 1){
            cout << "Nod" << endl;
        } else {
            int sg = 0;
            if (n % 2 == 1 && k == 2) a[1]--;
            for (int i = (n - 1) % 2 + 1; i <= n; i += 2){
                sg ^= a[i] - a[i - 1] - 1;
            }
            if (sg != 0){
                cout << "Nod" << endl;
            } else {
                cout << "Nic" << endl;
            }
        }
    }
    return 0;
}