Marbles(博弈SG函數)
Marbles
Gym - 101908B
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.
- (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
Input2Output
1 3
2 3
Y
Input
1Output
1 2
N個人理解:一堆石頭要是必勝的話,一定要全拿走吧,要不你拿一部分後手把剩下的全拿走就後手贏了。而NIM博弈的SG打表的話應該是 for(int i=0;i<x;i++)
題解:
首先,我們需要明白一個事實,在求SG函數時,一個點的後繼中如果有必敗態就把必敗態跳過,就是說求一個點的SG函數考慮的是他所有的非必敗態的後繼。所以對於本題來說,一個點的後繼狀態中如果有坐標軸或者對角線,因為坐標軸或者對角線對於當前的先手來說是必敗的,所以他肯定不會將點移動到坐標軸或者對角線上,所以後繼為坐標軸或者對角線直接跳過,不會參與求當前點的SG值中。 坤神說 一個數的SG值一定是它的後繼中的非必敗態,或者是這個位置不知道是否為勝或敗的狀態。nim博弈中,SG值為本身是因為假設一堆石子有5個,那麽我們一定要一口氣拿完5個才能勝,否則達到1~4的狀態都是必敗的。
{
vis[dfs(i)]=1;
} 這麽寫吧,就是把x之前的狀態全標記一個遍,所以對於0-x-1的每一個狀態都是以該狀態作為先手求SG值,所以0-x-1每個的SG值都是他必勝的狀態,所以對於x來說,我拿了一部分,到達了某個非零數,而那個數一定是後手必勝的,所以對於當前這一堆來說,先手唯一的必勝態就是把這一堆石頭全拿走,即SG[x]=x. 所以本題還需特判一下是否一開始有點在坐標軸或者對角線上,然後求每個點的SG值時,把坐標軸和對角線的後繼狀態跳過,因為是必敗態,而求SG值時不能考慮必敗態。
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 }
Marbles(博弈SG函數)