Marbles(博弈SG函数)
Marbles
Using 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 00through 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 00and 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
2
1 3
2 3
Y
1
1 2
N
题解:
首先,我们需要明白一个事实,在求SG函数时,一个点的后继中如果有必败态就把必败态跳过,就是说求一个点的SG函数考虑的是他所有的非必败态的后继。所以对于本题来说,一个点的后继状态中如果有坐标轴或者对角线,因为坐标轴或者对角线对于当前的先手来说是必败的,所以他肯定不会将点移动到坐标轴或者对角线上,所以后继为坐标轴或者对角线直接跳过,不会参与求当前点的SG值中。 坤神说 一个数的SG值一定是它的后继中的非必败态,或者是这个位置不知道是否为胜或败的状态。nim博弈中,SG值为本身是因为假设一堆石子有5个,那么我们一定要一口气拿完5个才能胜,否则达到1~4的状态都是必败的。
{
vis[dfs(i)]=1;
}
1 #include<iostream>
2 #include<cstdio>
3 #include<cstring>
4 #include<algorithm>
5 #define inf 999
6 using namespace std;
7 const int maxn=110;
8 int sg[maxn][maxn];
9 int get_sg(int x,int y)
10 {
11
12 if(sg[x][y]!=0)
13 return sg[x][y];
14 int vis[1100];
15 memset(vis,0,sizeof(vis));
16 for(int i=1;i<x;i++)
17 {
18 vis[get_sg(i,y)]=1;
19 }
20 for(int i=1;i<y;i++)
21 {
22 vis[get_sg(x,i)]=1;
23 }
24 for(int i=1;i<min(x,y);i++)
25 {
26 vis[get_sg(x-i,y-i)]=1;
27 }
28 for(int i=0;i<1100;i++)
29 {
30 if(!vis[i])
31 {
32 return sg[x][y]=i;
33 }
34 }
35 }
36 int main()
37 {
38 memset(sg,0,sizeof(sg));
39 sg[0][0]=0;
40 for(int i=0;i<maxn;i++)
41 sg[0][i]=inf;
42 for(int i=0;i<maxn;i++)
43 sg[i][0]=inf;
44 for(int i=1;i<maxn;i++)
45 {
46 for(int j=1;j<maxn;j++)
47 {
48 if(i==j)
49 sg[i][j]=inf;
50 }
51 }
52 get_sg(105,104);
53 int x,y;
54 int n;
55 int flag=0;
56 int sum=0;
57 scanf("%d",&n);
58 while(n--)
59 {
60 scanf("%d%d",&x,&y);
61 if(x==y||x==0||y==0)
62 {
63 flag=1;
64 }
65 sum^=sg[x][y];
66 }
67 if(flag)
68 {
69 puts("Y");
70 }
71 else
72 {
73 if(sum)
74 puts("Y");
75 else
76 puts("N");
77 }
78
79 }