hdu3032(sg博弈)

对于hdu3032题描述如下:


Paste_Image.png

Sample Input

2
3
2 2 3
2
3 3

Sample Output

Alice
Bob

如果不可以分成两堆,就是一个Nim的经典游戏。对于Nim游戏,有以下结论:

a1 xor a2 xor ...xor an != 0 必胜态
a1 xor a2 xor ...xor an == 0 必败态

首先,一旦从xor为零的状态取走至少一颗石子,xor就一定会变成非零,所以必败态只能转移到必胜态。
然后,观察xor的二进制表示最高位的1,选取石子数的二进制表示对应位也为1的某堆石子。只要从中取走使得该位变为零,且其余xor中的1也反转的数量的石子,xor就可以变为零。因此,必胜态总是可以转移到某个必败态。
所以,计算异或值就可以得到结果,非零则Alice必胜,为零则Bob必胜。

int n;//有n堆object
int arr[MAX_N];//每堆的个数

void solve() {
    int x = 0;//因为0与任何数异或都为此数本身
    for (int i = 0; i < n; ++i)
        x ^= arr[i];
    if (x != 0) puts("Alice");
    else puts("Bob");
}

利用Nim的思想对sg函数打表,可以找到此题的规律。先贴上打表代码:

#include <iostream>
#include <cstring>
using namespace std;

const int MAX_N = 100;
int sg[MAX_N];//sg函数
bool vis[MAX_N];//标记数组

void solve(int n) {
    memset(vis, false, sizeof(vis));
    for (int i = 0; i < n; ++i)
        vis[sg[i]] = true;
    for (int i = 1; i <= n; ++i)//因为可以分成两堆,如果三堆,就写三重循环
        for (int j = 1; j <= n; ++j) {
            if (i + j == n) vis[sg[i] ^ sg[j]] = true;
        }
    int i;
    for (i = 0; ; ++i)//没有i < n,如果都不成立,最后i = n
        if (!vis[i]) break;
    sg[n] = i;
    cout << "sg[" << n << "]=" << i << endl;
}

int main() {
    memset(sg, 0, sizeof(sg));
    for (int i = 1; i < 50; ++i) {
        solve(i);
    }
    return 0;
}

运行结果为:

Paste_Image.png

由此可以得到题解:

#include <iostream>
using namespace std;

int main() {
    ios::sync_with_stdio(false);
    cin.tie(NULL);
    int t;
    cin >> t;
    while (t--) {
        int n;
        cin >> n;
        int ans = 0;
        while (n--) {
            int val;
            cin >> val;
            if (val % 4 == 3) ans ^= val + 1;
            else if (val % 4 == 0) ans ^= val - 1;
            else ans ^= val;
        }
        cout << (ans ? "Alice" : "Bob") << endl;
    }
    return 0;
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 1.必胜必败态介绍# 假设存在一个游戏,游戏双方通过一定相同的策略进行游戏(假设都选择最优策略),直到一方无法进行...
    tdeblog阅读 4,093评论 1 0
  • http://acm.hdu.edu.cn/showproblem.php?pid=1525 题意:给你两个数,每...
    Gitfan阅读 4,571评论 0 0
  • 3.感受数学# 上一期的文章里我们仔细研究了Nim游戏,并且了解了找出必胜策略的方法。但如果把Nim的规则略加改变...
    tdeblog阅读 3,222评论 0 0
  • 按照用途分类出以下统计函数: AVEDEV 用途:返回一组数据与其平均值的绝对偏差的平均值,该函数可以评测数据(例...
    四方院祭司阅读 8,038评论 0 3
  • 游戏A:甲乙两人面对若干堆石子,其中每一堆石子的数目可以任意确定。例如图1所示的初始局面:共n=3堆,其中第一堆的...
    Gitfan阅读 3,762评论 0 0

友情链接更多精彩内容