练习赛补题----B - Marbles 博弈

sing marbles as a currency didn’t go so well in Cubicônia. In an attempt to make it up to his friends after stealing their marbles, the Emperor decided to invite them to a game night in his palace.

Of course, the game uses marbles, since the Emperor needs to find some use for so many of them. NN marbles are scattered in a board whose lines are numbered from 00 through LL and the columns numbered from 00 through CC. Players alternate turns. In his turn, a player must choose one of the marbles and move it. The first player to move a marble to position (0,0)(0,0) is the winner. The movements are limited so the game could be more interesting; otherwise, the first player could just move a marble to position (0,0)(0,0) and win. A movement consists in choosing an integer uu greater than 00 and a ball, whose location is denoted by (l,c)(l,c), and move it to one of the following positions, as long as it is inside the board:

(l−u,c)(l−u,c) or;
(l,c−u)(l,c−u) or;
(l−u,c−u)(l−u,c−u).
Note that more than one marble can occupy the same position on the board.

As the Emperor doesn’t like to lose, you should help him determine which games he should attend. Also, as expected, the Emperor always take the first turn when playing. Assuming both players act optimally, you are given the initial distribution of the marbles, and should find if it is possible for the Emperor to win if he chooses to play.

Input
The first line contains an integer NN (1≤N≤10001≤N≤1000). Each of the following NN rows contains two integers lili and cici indicating on which row and column the ii-th marble is in (1≤li,ci≤1001≤li,ci≤100).

Output
Your program should print a single line containing the character Y if it is possible for the Emperor to win the game or N otherwise.

Examples
Input
2
1 3
2 3
Output
Y
Input
1
1 2
Output
N

考虑把这个问题简单地转化为Nim游戏的模型。首先如果初始棋子有在x = 0, y = 0, y = x这三条线上的,特判一下输出Y。然后发现在游戏的过程中,将棋子移动到这三条线上就相当于必败,所有棋子肯定不选择移动到这三条线上。于是我们在计算SG函数的时候剔除掉这三条线。同时我们可以找到(1, 2)和(2, 1)这两个点,一旦棋子移动到这两个点,就无法继续移动了,否则对方就会获得胜利。那么(1, 2)和(2, 1)这两个点就对应着Nim游戏里的某一堆石子被取完了。最后的结束条件是所有的棋子都在(1, 2)或者(2, 1)了。
最后的解法:将终结态设为(1, 2)和(2, 1)两个点,SG函数值设为0。DFS求所有点的SG函数,过程中跳过两个坐标轴以及y = x这条线上的点。将n个棋子的位置上的SG函数求异或,最后的结果是0就输出N,否则是Y

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int inf = 0x3f3f3f3f;
#define mp make_pair
#define pb push_back
#define fi first
#define se second

int sg[105][105];
bool vis[205];

void SG()
{
    //里面去除了x轴,y轴,斜线的情况
    for(int i = 1;i <= 100;++i){
        for(int j = 1;j <= 100;++j){
            if(i == j) continue;
            memset(vis,0,sizeof(vis));
            int len = max(i,j);
            for(int k = 1;k <= len;++k){
                int dx = i - k;
                int dy = j - k;
                if(dx > 0 && dx != j){
                    //后继态为(dx,j)
                    vis[sg[dx][j]] = 1;
                }
                if(dy > 0 && dy != i){
                    vis[sg[i][dy]] = 1;
                }
                if(dx > 0 && dy > 0 && dx != dy){
                    vis[sg[dx][dy]] = 1;
                }
            }
            //计算当前状态的sg值
            int g = 0;
            while(vis[g]){
                g++;
            }
            sg[i][j] = g;
        }
    }
}

int main()
{
    SG();
    int n;
    scanf("%d",&n);
    bool flag = false;
    int ans = 0;
    for(int i = 0;i < n;++i){
        int a,b;
        scanf("%d %d",&a,&b);
        if(flag) continue;
        if(a == 0 || b == 0 || a == b){
            flag = true;
            continue;
        }
        ans ^= sg[a][b];
    }
    if(flag){
        printf("Y\n");
    }else{
        if(ans){
            printf("Y\n");
        }else{
            printf("N\n");
        }
    }
    return 0;
}

发布了269 篇原创文章 · 获赞 33 · 访问量 8万+

猜你喜欢

转载自blog.csdn.net/qq_36386435/article/details/88722337