You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2.0 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

HDU 1730 Northcott Game 题目传送门

图1

图2

一、解题思路

  • 把同一行棋子之间的距离看做石子数。两个棋子紧挨着,就表示这堆石子个数为零。否则石子数量就是白色棋子坐标与黑色棋子坐标差+1。

  • 如果黑棋选择扩大距离(向左走) 白棋足够聪明,直接跟进,贴上黑棋,这样,本行黑棋不管怎么操作,都会被跟进,直到遇到左侧边界,那么,黑棋将在本行无路可走,只能再去其它行尝试,也就是黑棋在本行没有占到便宜,被迫进入下一行。换句话说,在本题中不能扩大距离,只能缩小距离,即拿走一些石子。

  • 如果黑棋选择缩小距离(向右走) 对比Nim游戏就是拿走一些石子一共有N堆石子每次只能从某一堆中拿走一些石子>=1 && <=a[i])个。问是先手必胜还是先手必败这不就是经典的Nim游戏吗

直接以坐标差+1做为石子个数,构建Nim游戏,计算异或和,是0则先手必败,否则先手必胜。

二、模拟第二组数据, 黑棋是怎么赢的

#include <bits/stdc++.h>

using namespace std;
int main() {
    int res = 2 ^ 0 ^ 0;
    printf("%d\n", res);           //异或和
    printf("%d\n", res ^ 2);       //剩余几个 输出0
    printf("%d\n", 2 - (res ^ 2)); //取走几个 输出2
    return 0;
}

三、实现代码

#include <bits/stdc++.h>
using namespace std;
int main() {
    int n, m;
    while (~scanf("%d %d", &n, &m)) {
        int res = 0;
        for (int i = 1; i <= n; ++i) {
            int a, b;
            scanf("%d %d", &a, &b);
            res = res ^ (abs(a - b) - 1);
        }
        if (res == 0)
            puts("BAD LUCK!");
        else
            puts("I WIN!");
    }
    return 0;
}