尧图网站建设 尧图网络
  • 首页
  • 关于我们
  • 服务项目
  • 案例展示
  • 建站流程
  • 资讯中心
  • 联系我们
首页/资讯中心/详情

Nimm Game

Nimm Game
📅 发布时间:2026/6/19 2:43:22

模型介绍

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. 教学价值:理解博弈论基本概念的理想模型

相关新闻

  • 基于C++的远程键盘监控器设计与实现 - 教程
  • 2025年医药冷链运输厂家权威推荐榜:药品/临床样本/CAR-T/蛋白/诊断试剂/生物制品/血液/细胞/芯片全程温控,冷藏车/冷藏箱/保温箱/干冰/液氮及国际冷链进出口专业服务
  • 零代码改造 + 全链路追踪!Spring AI 最新可观测性详细解读

最新新闻

  • 嵌入式MCU电气特性与FLASH操作深度解析:从数据手册到稳定设计
  • 2026 郑州八大装修公司综合实力排行榜 - GrowthUME
  • 爱回收到店估价和到手价差多少?iPhone 15 Pro实测报告 - 新闻快传
  • 2026沈阳非急救转运救护车TOP5盘点|辽中同城、浑河跨桥、棋盘山山地、院区转诊首选康跃转运 - 吉修匠
  • 2026长沙防水补漏权威指南:卫生间/屋面/外墙/地下室正规施工+透明报价+避坑全攻略 - 苏易修缮
  • 爱回收靠谱吗?一个测评博主的深度复盘 - 新闻快传

日新闻

  • 5分钟掌握Python进化算法:Geatpy高性能优化工具完全指南
  • Microchip 24AA044 EEPROM选型与应用全指南:从参数解析到实战编程
  • 华为的鸿蒙到底有多牛?为什么称作遥遥领先?

周新闻

  • 3步解锁iOS设备:applera1n激活锁绕过完全指南
  • 39 2026 人工智能证书终极盘点,普通人选 AI 证书可以从这些方向入手
  • Redis 暴露公网有多危险?从端口检查到补救步骤

月新闻

  • 【总结】入门篇:50句话让你记住架构核心概念
  • WeChatMsg技术方案解析:实现Mac微信数据自主管理的完整解决方案
  • WeChatMsg:革新性微信数据备份方案,打造你的专属数字记忆库

关于尧图

  • 公司简介
  • 团队介绍
  • 企业文化
  • 荣誉资质

服务项目

  • 定制开发
  • 电商建站
  • UI 设计
  • 运维服务

快速链接

  • 案例展示
  • 建站流程
  • 常见问题
  • 资讯中心

联系方式

  • 📍北京市朝阳区互联网产业园 A 座 10 层
  • 📞400-888-8888
  • ✉️contact@rkmt.cn
  • 🕐周一至周日 9:00-21:00

© 2024 北京尧图网络科技有限公司 版权所有 | 京 ICP 备 XXXXXXXX 号