首页 > 其他分享 >博弈论nim游戏

博弈论nim游戏

时间:2022-10-31 17:01:36浏览次数:43  
标签:游戏 nim int res 博弈论 cin SG

nim游戏

给定n堆物品,第i堆物品有Ai个,两名玩家轮流行动,每次可以任选一堆,取走任意多个物品,可把一堆取光,但不能不取。取走最后一件物品的人获胜。


定理:nim游戏先手必胜,当且仅当A1 xor A2 xor ... xor An != 0

xor 不进位加法
从无到有的过程是最难的,nim游戏是困扰了多少代人的难题!

定理证明(参考算阶)

#include <iostream>
using namespace std;
int main()
{
    int n;cin >> n;
    int res = 0;
    while(n --)
    {
        int x; cin >> x;
        res ^= x;
    }
    if(res) puts("Yes");
    else    cout << "No" << endl;
    return 0;
}

Mex运算

Mex运算就是除去本身以外其他非负整数的集合中的最小值,如MEX{1}=0,MEX{0,1,2,4,5}=3

SG函数

在有向图游戏中,对于每个节点x,设从x出发共有k条有向边,分别到达节点y1,y2,···,yk,定义SG(x)为x的后继结点y1,y2,···,yk的SG函数值构成的集合再执行Mex运算的结果,即:
SG(X) = mex({SG(y1), SG(y2),···, SG(yk)})

多个SG游戏的最终结果为每个SG函数值的异或和,异或和为0即为必败点,反之为必胜点

  1. 集合-Nim游戏
    题目
    提交记录
    讨论
    题解
    视频讲解

给定 n
堆石子以及一个由 k
个不同正整数构成的数字集合 S

现在有两位玩家轮流操作,每次操作可以从任意一堆石子中拿取石子,每次拿取的石子数量必须包含于集合 S
,最后无法进行操作的人视为失败。

问如果两人都采用最优策略,先手是否必胜。

输入格式

第一行包含整数 k
,表示数字集合 S
中数字的个数。

第二行包含 k
个整数,其中第 i
个整数表示数字集合 S
中的第 i
个数 si

第三行包含整数 n

第四行包含 n
个整数,其中第 i
个整数表示第 i
堆石子的数量 hi

输出格式

如果先手方必胜,则输出 Yes。

否则,输出 No。

数据范围

1≤n,k≤100
,
1≤si,hi≤10000

输入样例:

2
2 5
3
2 4 7
输出样例:

Yes

#include <iostream>
#include <cstring>
#include <unordered_set>
using namespace std;
const int N = 110, M = 10010;
int n, k;
int s[N], f[M];

//用记忆化搜索实现求sg函数
int sg(int x)
{
    //定义一个哈希表存x能到达的所有状态
    unordered_set<int>S;
    //如果当前状态已经到达过了,我们就直接返回,保证每个状态只到达过一次,这样便能保证每个状态不会重复搜索
    if(f[x] != -1)    return f[x];
    //枚举当前状态能到达的所有状态也就是当前结点的所有后继节点
    for(int i = 0; i < n; ++ i)
    {
        int t = s[i];
        if(x - t >= 0)  S.insert(sg(x - t));
    }
    //对当前x的所有后继结点进行mex操作
    for(int i = 0; ; ++ i)
        if(!S.count(i)) return f[x] = i;
}

int main()
{
    cin >> n;
    memset(f, -1, sizeof f);
    for(int i = 0; i < n; ++ i) cin >> s[i];
    cin >> k;
    int res = 0;
    while(k --)
    {
        int x;cin >>x;
        res ^= sg(x);
    }
    if(res) cout << "Yes" << endl;
    else    cout << "No" << endl;
    return 0;
}

标签:游戏,nim,int,res,博弈论,cin,SG
From: https://www.cnblogs.com/cxy8/p/16844933.html

相关文章

  • #打卡不停更# 简单的JS鸿蒙小游戏——飞行棋之页面构建
    前言飞行棋大家应该都玩过吧,红、绿、黄、蓝四名玩家轮流掷骰子移动棋子,争先到达终点,期间还要提防己方棋子不被击落。今天就先带大家学习下如何完成飞行棋游戏的简单布局。......
  • UVA10384 推门游戏 The Wall Pushers(IDA_,A_)
    题目大意给你一个\(4\times6\)的网格图,网格边缘上可能有墙。对于每一个网格有一个权值\(val\),其中\[\begin{aligned}val=&&1(\text{如果这个网格左边缘(西边缘)有墙......
  • 【XSY3990】Alice 和 Bob 双在玩游戏(博弈,dp,拓扑,背包)
    题面Alice和Bob双在玩游戏题解注意到这里一个人无法操作后,另一个人也不一定无法操作(即不像普通的取石子游戏一样),所以考虑转化一下他们各自的最优策略:双方都想让自己......
  • P8818 CSP-S 2022 策略游戏
    P8818CSP-S2022策略游戏-洛谷|计算机科学教育新生态(luogu.com.cn)矩阵这个描述就是障眼法。翻译一下题目:A在\(a[l_1\cdotsr_1]\)中选择一个\(x\),然后B......
  • 学习记录23java拼图小游戏
    拼图目标GUI(GraphicalUserInterface,图形用户接口)这是指采用图形化的方式显示操作界面,几乎所有的语言都有GUI的知识java中有两套完整的体系:AWT包(出现的比较早,可能......
  • Google 登录,海外游戏接入
    ##准备1,开发者注册(需要25美元,国内任意一家visa信用卡都可以绑定支付,推荐招商银行的),商家账号注册(需要填写资料)2,创建项目-打开网址https://console.cloud.google.com/,......
  • 游戏渠道接入问题,quick接入prefix为空
    如果sdk接入时候游戏Application没有继承QuickSdkApplication,那么在登录时候获取到的Userinfo.getUID(),将会默认拼接一个0.导致跟渠道的登录验证不通过输出:0{$uid}......
  • 55.jump-game 跳跃游戏
    问题描述55.跳跃游戏解题思路从后向前遍历,只要nums[j]能由nums[j-1]或者更前面的点跳到,那么终点就从nums[j]变成nums[j-1]或更前面的点。代码#include<vector>u......
  • 45.jump-game-ii 跳跃游戏II
    问题描述45.跳跃游戏II解题思路外循环还是从末尾向前遍历,内循环从前往后遍历,每次找能到达终点的索引最小的位置,该位置作为新的终点,同时步数cnt++。代码#include<vect......
  • [CSP-S 2022] 策略游戏
    link历年来最简单的T2。我们直接暴力分讨:首先不考虑\(0\)。A区间全为正数(1)B区间全为正数,A取最大,B取最小(2)B区间有正有负,A取最小,B取最小(3)B区间......