首页 > 其他 > 详细

简单博弈论

时间:2021-02-18 10:43:59      阅读:42      评论:0      收藏:0      [点我收藏+]

Nim游戏

如果 \(a_1\) ^ \(a_2\) ^ \(a_3\) ^ \(\ldots\) ^ \(a_n\) = 0,则先手必败,否则必胜。

题意:n 堆石子,两位玩家可以从任意一堆中拿任意数量的石子,但是不能不拿,问先手是否必胜。

#include <bits/stdc++.h>
using namespace std;

const char nl = ‘\n‘;
//const int N =

int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int n;
    cin >> n;

    int res = 0;
    for (int i = 0, x; i < n; ++i){
        cin >> x;
        res ^= x;
    }
    if (res) cout << "YES" << nl;
    else cout << "NO" << nl;

    return 0;
}

SG 函数

\(sg(x_1)\) ^ \(sg(x_2)\) ^ \(sg(x_3)\) ^ \(\ldots\) ^ \(sg(x_n)\) = 0,则先手必败,否则必胜。

题意:给定 n 堆石子以及 m 个不同正整数构成的集合 S,两位玩家只能从任意一堆中拿指定数量的石子,该数量必须包含于 S 集合中,问先手是否必胜。

#include <bits/stdc++.h>
using namespace std;

const char nl = ‘\n‘;
const int N = 1e5 + 50;

int n, m;
int s[N], f[N];

int sg(int x){
    if (f[x] != -1) return f[x];

    unordered_set<int> S;
    for (int i = 0; i < m; ++i){
        if (x >= s[i]) S.insert(sg(x - s[i]));
    }
    for (int i = 0; ; ++i)
        if (!S.count(i)) return f[x] = i;
}

int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    cin >> m;
    for (int i = 0; i < m; ++i) cin >> s[i];

    cin >> n;
    memset(f, -1, sizeof(f));

    int res = 0;
    for (int i = 0, x; i < n; ++i){
        cin >> x;
        res ^= sg(x);
    }
    if (res) cout << "YES" << nl;
    else cout << "NO" << nl;

    return 0;
}

简单博弈论

原文:https://www.cnblogs.com/xiaoran991/p/14410384.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!