新疆大学ACM-ICPC程序设计竞赛五月月赛(同步赛) G chess(SG函数, 威佐夫博弈)

题意:竟然是英文,,,难受,就是给你一个10000*1000的棋盘,告诉你当前棋子离左下角顶点的距离是多少,其中你可以向左走任意步,或者向下走任意步,或者沿着斜对角走任意步,谁到左下角顶点赢。

思路:我直接小范围利用SG函数打了个表,(写了很久很久很久。。。)之后找出规律推出了公式,写过了之后求网上搜题解发现是个威佐夫博弈。。。仔细想了想确实啊 ,威佐夫就是有两堆石子,你可以取一堆石子中的任意个或者两堆石子中取出相同个,,这不就是一个往左和往下,一个斜对角嘛,直接写就过了,。。

上代码:

#include <bits/stdc++.h>
using namespace std;
const int maxn = 10000+10;
//int SG[maxn][maxn];
int vis[maxn];
int dir[3][2] = {-1,0,0,-1,-1,-1};
map<int,int>G;
void init()
{
//  memset(SG,0,sizeof(SG));  小范围打表。。 
/*  for(int i = 0 ; i < 100 ; i++)
    {
        SG[i][0] = 1;
        SG[0][i] = 1;
        SG[i][i] = 1;
    }
    for(int i = 1 ; i < 100 ; i++)
    {
        for(int j = 1 ; j < 100 ; j++)
        {
            if(i == j )  continue;
            memset(vis,0,sizeof(vis));
            for(int k = 0 ; k < 3 ; k++)
            {
                int dx = i , dy = j;
                while(dx >=0 && dy >= 0)
                {
                    dx = dx + dir[k][0];
                    dy = dy + dir[k][1];
                    if(dx < 0 || dy <0) break;
                    vis[SG[dx][dy]] = 1;
                }
            }
            for(int k = 0 ; ; k++)
            {
                if(!vis[k])
                {
                    SG[i][j] = k;
                    break;
                }
            }
        }
    }*/
    // 1 2 / 3 5 / 4 7 / 6 10 / 8 13 / 9 15 / 发现规律其实就是每次差的值是 1 2 3 4 5 6 ....  
    G.clear();
    int sub = 1;
    int s = 1;
    for(int i = 1 ; i <= maxn ; i++)//根据规律去打表 
    {
        if(vis[i] || vis[i+sub]) continue;
        if(i+sub > maxn) break;
        G[i] = i + sub;
    //  printf("%d  %d \n",i,i+sub);
        vis[i] = 1 , vis[i+sub] = 1;
        sub++;
         
    }
     
}
int main()
{
    int n,m;
    init();
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        if(n > m ) swap(n,m);
        if(G[n] != m) puts("Xiao Ren");
        else puts("Lao Wang");
    }
}

另附威佐夫代码。。

#include <stdio.h>
#include <iostream>
using namespace std;
int main(){
    int a, b;
    while(~scanf("%d%d", &a, &b)){
        if(a>b) swap(a,b); 
        long k = b-a;
        printf("%s\n", a==(int)(1.618033989*k) ? "Lao Wang" : "Xiao Ren");
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/wjmwsgj/article/details/80169770