博弈论 Nim游戏

    本文参考链接:https://www.geeksforgeeks.org/combinatorial-game-theory-set-2-game-nim/

给定许多堆,其中每堆包含一些数量的石头。在每一回合中,玩家只能选择一堆并从该堆中移除任意数量的石子(至少一个)。无法移动的玩家被视为输掉游戏(即,拿走最后一颗石头的玩家获胜

    举个栗子:

    存在三堆石子和两个玩家

    石子:1、4、5

    玩家:A、B

1、比赛胜利因素

    1、最先开始的玩家

    2、堆的初始配置

如果 A玩家 和 B玩家 都发挥最佳(即,他们没有犯任何错误),那么如果游戏开始时的 所有堆中石子的异或和 不为零,那么先开始的玩家就一定会获胜。否则,如果 所有堆中石子的异或和 评估为零,那么玩家 A 肯定会输。

2、最优策略

    1、如果“n”个数字的异或和已经为零,则不可能通过数字的单次减少来使异或和为零。

    2、如果“n”个数字的异或和非零,那么至少有一种方法可以减少一个数字,异或和为零。

即存在两种状态 冷状态热状态

    冷状态:无论当前玩家怎么取剩下的都是热状态。即第一种情况

    热状态:当前玩家可以通过操作使得剩下的状态变为冷状态,即第二种情况

让我们将上述定理应用到上面玩的游戏中。第一局比赛中, A先开始,比赛开始时 所有堆中石子的异或和 为3 XOR 4 XOR 5 = 2,是非零值,因此A获胜。而在第二盘游戏中,当牌堆的初始配置为1、4、5, A先开始时, A注定会输,因为游戏开始时 所有堆中石子的异或和 是1 XOR 4 XOR 5 = 0 。

#include <iostream>
#include <vector>

using namespace std;

// 判断当前玩家是否处于必胜态
bool isWinningPosition(const vector<int>& piles) {
    int nimSum = 0;
    for (int pile : piles) {
        nimSum ^= pile;  // 计算所有堆的异或和
    }
    return nimSum != 0;  // 如果 Nim-Sum 不为 0,则当前为必胜态
}

int main() {
    int n;  // 堆的数量
    cout << "请输入堆的数量:";
    cin >> n;

    vector<int> piles(n);
    cout << "请输入每堆的石子数量:" << endl;
    for (int i = 0; i < n; ++i) {
        cin >> piles[i];
    }

    if (isWinningPosition(piles)) {
        cout << "当前玩家处于必胜态。" << endl;
    } else {
        cout << "当前玩家处于必败态。" << endl;
    }

    return 0;
}

posted @ 2024-09-09 21:34  xiaoluosibky  阅读(63)  评论(0)    收藏  举报