当前位置: 首页 > news >正文

Nimm Game

模型介绍

Nim Game 是博弈论中最著名且最重要的模型之一,规则如下:

  • \(n\) 堆物品,每堆分别有 \(a_1,a_2,\cdots,a_n\) 个;
  • 两名玩家轮流操作;
  • 每次只能从某一堆中取任意数量的物品(至少 \(1\) 个,至多取完该堆);
  • 最后取光所有物品的玩家获胜。

历史背景

Nim Game 的历史可以追溯到中国古代,但现代博弈论中的系统研究始于 \(1901\) 年 Charles L. Bouton 的论文。Bouton 提出了完整的理论解决方案,使 Nim Game 成为第一个被完全解决的组合博弈问题。

核心结论与证明

Bouton 定理

对于 Nim Game,定义尼姆和(Nim-sum)为所有堆大小的异或和:

\[S=a_1\oplus a_2\oplus\cdots\oplus a_n \]

结论:

  • 如果 \(S=0\),先手必败;
  • 如果 \(S\neq0\),先手必胜。

证明

基本思路:

  • 终局状态(所有堆为 \(0\))的尼姆和为 \(0\),是必败态;
  • 从尼姆和非 \(0\) 的状态,总可以一步操作到达尼姆和为 \(0\) 的状态;
  • 从尼姆和为 \(0\) 的状态,任何操作都会到达尼姆和非 \(0\) 的状态。

详细证明:

  1. 引理 \(1\):如果 \(S=0\),则任何合法操作都会使 \(S\neq0\),证明:
  • 假设从第 \(i\) 堆取走 \(k\) 个物品 \((0<k\le a_i)\)
  • 新的堆大小 \(a_i'= a_i-k\)
  • 新的尼姆和 \(S'=S\oplus a_i\oplus a_i'=0\oplus a_ᵢ\oplus(a_i-k)=a_i\oplus(a_i-k)\)
  • 由于 \(k>0\),所以 \(a_i\neq a_i-k\),因此 \(S'\neq0\)
  1. 引理 \(2\):如果 \(S\neq0\),则存在合法操作使 \(S'=0\),证明:
  • \(S\) 的最高位是第 \(d\) 位;
  • 存在某个 \(a_i\) 的第 \(d\) 位为 \(1\)(否则 \(S\) 的第 \(d\) 位不可能为 \(1\));
  • \(x=a_i\oplus S\),则 \(x<a_i\)(因为 \(a_i\)\(x\) 在第 \(d\) 位以上的位相同,但 \(a_i\) 的第 \(d\) 位为 \(1\)\(x\) 的第 \(d\) 位为 \(0\));
  • 从第 \(i\) 堆取走 \(a_i-x\) 个物品,使该堆变为 \(x\)
  • 新的尼姆和 \(S'=S\oplus a_i\oplus x=S\oplus a_i\oplus(a_i\oplus S)=0\)

归纳证明:

  • 基础:终局状态 \(S=0\) 是必败态;
  • 归纳:
  1. 如果 \(S=0\),任何操作都到 \(S\neq0\)(引理 \(1\));
  2. 如果 \(S\neq0\),存在操作到 \(S=0\)(引理 \(2\));
  • 因此结论成立。

代码实现

基础判断与策略

#include <bits/stdc++.h>
#define int long longusing namespace std;// 计算尼姆和
int calculateNimSum(const vector<int>& piles) {int nim_sum = 0;for (int pile : piles) {nim_sum ^= pile;}return nim_sum;
}// 判断先手是否必胜
bool canWinNim(const vector<int>& piles) { return calculateNimSum(piles) != 0; }// 找到必胜策略
pair<int, int> findWinningMove(const vector<int>& piles) {int nim_sum = calculateNimSum(piles);if (nim_sum == 0) {return {-1, -1};  // 没有必胜策略}// 找到第一个可以操作的堆for (int i = 0; i < piles.size(); i++) {int target = piles[i] ^ nim_sum;if (target < piles[i]) {return {i, piles[i] - target};}}return {-1, -1};  // 理论上不会执行到这里
}// 显示二进制表示(用于理解)
void showBinaryAnalysis(const vector<int>& piles) {cout << "堆状态分析:" << endl;int nim_sum = 0;for (int i = 0; i < piles.size(); i++) {cout << "堆 " << i << ": " << piles[i] << " = " << bitset<8>(piles[i]) << endl;nim_sum ^= piles[i];}cout << "尼姆和: " << nim_sum << " = " << bitset<8>(nim_sum) << endl;cout << "先手" << (nim_sum == 0 ? "必败" : "必胜") << endl;
}

完整游戏模拟

#include <bits/stdc++.h>
#define int long longusing namespace std;class NimGame {private:vector<int> piles;public:NimGame(const vector<int>& initialPiles) : piles(initialPiles) {}bool isGameOver() {for (int pile : piles) {if (pile > 0) return false;}return true;}bool isValidMove(int pileIndex, int takeCount) { return pileIndex >= 0 && pileIndex < piles.size() && takeCount > 0 && takeCount <= piles[pileIndex]; }bool makeMove(int pileIndex, int takeCount) {if (!isValidMove(pileIndex, takeCount)) return false;piles[pileIndex] -= takeCount;return true;}void printState() {cout << "当前堆状态: ";for (int i = 0; i < piles.size(); i++) {cout << "堆" << i << ":" << piles[i] << " ";}cout << endl;}// 电脑的智能移动pair<int, int> computerMove() {auto move = findWinningMove(piles);if (move.first == -1) {// 必败态,随机移动for (int i = 0; i < piles.size(); i++) {if (piles[i] > 0) {move = {i, 1};  // 随便取1个break;}}}makeMove(move.first, move.second);return move;}const vector<int>& getPiles() { return piles; }
};void playNimGame() {vector<int> initialPiles = {3, 4, 5};NimGame game(initialPiles);bool playerTurn = true;cout << "Nim Game 开始!" << endl;cout << "初始堆: ";for (int pile : initialPiles) cout << pile << " ";cout << endl;showBinaryAnalysis(initialPiles);cout << endl;while (!game.isGameOver()) {game.printState();if (playerTurn) {int pile, count;cout << "你的回合 - 输入堆索引和取的数量: ";cin >> pile >> count;if (!game.makeMove(pile, count)) {cout << "无效移动!请重新输入。" << endl;continue;}} else {auto move = game.computerMove();cout << "电脑: 从堆" << move.first << "取" << move.second << "个" << endl;// 显示分析showBinaryAnalysis(game.getPiles());cout << endl;}playerTurn = !playerTurn;}cout << "游戏结束!" << (playerTurn ? "电脑" : "玩家") << "获胜!" << endl;
}

变种题目与解法

变种 1:最后取者输(Misère Nim)

  • 规则:其他规则相同,但最后取物品的人输;
  • 解法:
  1. 当所有堆都只有 \(1\) 个物品时:如果堆数是奇数,先手必败;偶数则先手必胜;
  2. 其他情况:与正常 Nim 相同,但需要特殊处理全1的情况。
bool canWinMisereNim(const vector<int>& piles) {int nim_sum = 0;bool all_ones = true;for (int pile : piles) {nim_sum ^= pile;if (pile > 1) all_ones = false;}if (all_ones) {return (piles.size() % 2) == 0;  // 堆数为偶数时先手必胜} else {return nim_sum != 0;  // 与正常Nim相同}
}

变种 2:受限 Nim(取石子上限)

  • 规则:每次最多取 \(k\) 个物品;
  • 解法:计算每堆的模 \(k+1\) 值,然后用正常 Nim 策略。
bool limitedNim(const vector<int>& piles, int max_take) {vector<int> mod_piles;for (int pile : piles) {mod_piles.push_back(pile % (max_take + 1));}return calculateNimSum(mod_piles) != 0;
}

变种 3:阶梯 Nim

  • 规则:物品在阶梯上,只能从某一阶移动到下一阶;
  • 解法:只考虑奇数阶(或偶数阶)的物品数量。
bool staircaseNim(const vector<int>& steps) {int nim_sum = 0;for (int i = 1; i < steps.size(); i += 2) {  // 只考虑奇数阶nim_sum ^= steps[i];}return nim_sum != 0;
}

变种 4:Moore's Nim

  • 规则:每次可以从最多 \(k\) 堆中取物品;
  • 解法:计算每堆的二进制表示,检查每一位 \(1\) 的个数模 \(k+1\)
bool mooresNim(const vector<int>& piles, int k) {const int MAX_BITS = 32;for (int bit = 0; bit < MAX_BITS; bit++) {int count = 0;for (int pile : piles) {if (pile & (1 << bit)) {count++;}}if (count % (k + 1) != 0) {return true;  // 先手必胜}}return false;  // 先手必败
}

总结

Nim Game 在博弈论中具有核心地位,其重要性体现在:

  1. 理论基础:第一个被完全解决的组合博弈问题
  2. 优美解法:简单的异或运算解决复杂博弈问题
  3. 广泛适用:通过Sprague-Grundy定理扩展到所有公平组合博弈
  4. 教学价值:理解博弈论基本概念的理想模型
http://www.jsqmd.com/news/18569/

相关文章:

  • 2025年陶瓷过滤机厂家权威推荐榜:真空/盘式/矿用/全自动/真空带式陶瓷过滤机,固液分离设备,尾矿处理设备,圆盘过滤机专业选购指南
  • 基于C++的远程键盘监控器设计与实现 - 教程
  • 2025年医药冷链运输厂家权威推荐榜:药品/临床样本/CAR-T/蛋白/诊断试剂/生物制品/血液/细胞/芯片全程温控,冷藏车/冷藏箱/保温箱/干冰/液氮及国际冷链进出口专业服务
  • 2025 装修公司推荐排行榜单:江苏/浙江/制药厂/厂房/实验室/办公室/店面/净化室装修公司推荐,实测老客复购率与专业能力
  • 零代码改造 + 全链路追踪!Spring AI 最新可观测性详细解读
  • xupt 3g移动开发实验室二面
  • 2025年连铸机设备厂家权威推荐榜:扇形段/大包回转台/钢包中间罐/结晶器总成/拉矫机/输送辊道等核心部件专业解析
  • React使用useLocation监听url地址变化,工具URLSearchParams获取参数
  • 碰一碰,秒更新!游戏近场快传助力多人联机无缝组队
  • Moka AI 驱动 HR系统转型实践案例:从技术探索到组织价值落地的全链路解析
  • 2025年服饰厂家权威推荐榜:棒球帽,卫衣,羽绒服源头厂家精选,潮流设计与舒适品质口碑之选
  • 字节跨平台框架 Lynx 开源:一个 Web 开发者的原生体验
  • 2025年10月北京昌平回龙观酒店推荐:对比评测榜助您锁定高性价比会议与度假之选
  • SLS指标监控
  • 2025年10月北京昌平回龙观酒店推荐榜:五家对比评测与实用选择指南
  • 阿里云SLB指标监控
  • 2025 年最新华侨生联考培训机构口碑推荐榜:聚焦优质教学服务,助力考生高效备考,附详细选择指南
  • 洛谷题单指南-进阶数论-CF632D Longest Subsequence
  • 2025 年最新推荐锯床实力厂家排行榜:龙门 / 数控 / 金属带锯床等多类型设备权威甄选优质企业角度/金属带/双立柱/小型/大型锯床厂家推荐
  • 2025织带厂家权威推荐:东莞永沣专业定制防水织带与飞织鞋面
  • 2025发电机厂家实力推荐:三澳新能源科技专业制造,高效稳定动力解决方案
  • 阿里云PolarDB监控
  • 2025年织带类厂家权威推荐榜:防水织带、鞋垫、编织包/针织包/飞织包包、松紧带、鞋带、织带、飞织鞋面源头企业精选
  • 2025年10月护眼台灯品牌评测推荐:十强榜单对比与理性选购指南
  • 阿里云Elasticsearch指标监控
  • 阿里云MongoDB副本集指标监控
  • UV紫外相机在工业视觉检测中的应用 - 实践
  • 2025 年最新推荐销轴厂家排行榜:含 8.8 级 / 4.8 级 / 10.9 级 / 镀锌 / 高强度 / 发黑 / 异型 / 非标 / 农机销轴公司推荐
  • 阿里云ECS监控
  • Wythoff Game