• 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. 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:

    • (lu,c)(l−u,c) or;
    • (l,cu)(l,c−u) or;
    • (lu,cu)(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 (1N10001≤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 (1li,ci1001≤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
    题解:
      首先,我们需要明白一个事实,在求SG函数时,一个点的后继中如果有必败态就把必败态跳过,就是说求一个点的SG函数考虑的是他所有的非必败态的后继。所以对于本题来说,一个点的后继状态中如果有坐标轴或者对角线,因为坐标轴或者对角线对于当前的先手来说是必败的,所以他肯定不会将点移动到坐标轴或者对角线上,所以后继为坐标轴或者对角线直接跳过,不会参与求当前点的SG值中。 坤神说 一个数的SG值一定是它的后继中的非必败态,或者是这个位置不知道是否为胜或败的状态。nim博弈中,SG值为本身是因为假设一堆石子有5个,那么我们一定要一口气拿完5个才能胜,否则达到1~4的状态都是必败的。
     个人理解:一堆石头要是必胜的话,一定要全拿走吧,要不你拿一部分后手把剩下的全拿走就后手赢了。而NIM博弈的SG打表的话应该是
    for(int i=0;i<x;i++)
    {
      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 }
  • 相关阅读:
    AJAX 弹出窗消息类
    正则表达式验证总结
    Coolite 三列布局演示
    Coolite: Button、TextField、DataField、ComBox
    页面返回
    Coolite GridPanel 操作之一:获取gridpanel 选中行的记录信息
    页面上Enter 键禁用
    new、abstract、virtual、override,sealed关键字区别和使用代码示例
    Coolite TreePanel 操作之一:TreePanel 刷新
    调用WCF出现 The remote server returned an error: (401) Unauthorized. 错误
  • 原文地址:https://www.cnblogs.com/1013star/p/10088807.html
Copyright © 2020-2023  润新知