HDU5754 Life Winner Bo

題目連接:http://acm.hdu.edu.cn/showproblem.php?pid=5754


【題意】B和G,在一個N*M的棋盤上下棋,棋子初始位置再(1,1),目標是走到(n,m)。棋子移動的位置必須是在其右下方向,及移動後的位置(x',y')相對原位置(x,y),x'≥x,y'≥y,同時棋子不能超出棋盤界限。有4種棋子,國王,馬,車,皇后。棋子的移動規則同國際象棋,及國王可以向四周8個格子移動一格,題中可以向右下3個格子移動;馬可以走日字,題中可以向右下兩個位置移動;車可以直線無限格移動,題中可以向下和右移動無限格;皇后可以直線和斜線無限格移動,題中可以向下,右,右下三個方向無限格移動。每次給定棋子類型和棋盤大小,兩人輪流移動棋子,誰先將棋子移動至(n,m)誰贏,棋子無法移動至(n,m)爲平局。


【分析】由於每次只進行一個遊戲,採用sg值的思想,區別爲必敗態標記0,必勝態標記1,平局標記-1。預處理出1000*1000棋盤四種棋子的所有解。國王:利用&操作判斷三個後繼是否存在0,存在則該格子是必勝態填1,否則爲必敗態填0;馬:由於馬存在平局的可能,判斷馬的兩個後繼是否存在0,存在則該格子爲必勝態填1,否則判斷是否存在-1,存在該格子爲平局態填-1,都爲1則該格子爲必敗態填0;車:簡單找一下規律可以發現只有行列相等的時候是必敗態填0,其他均爲必勝態填1;皇后:比賽時通過打表找到的規律,由於對稱,以i<j舉例。以(0,0)爲終點的話,下面的點是(1,2),(3,5),(4,7)。規律每次i=i+1,若i的數之前未出現過,j=j+2,該格子爲必敗態填0;若i出現過,j=j+1,不進行處理繼續循環。比賽結束被告知皇后就是是威佐夫博弈=.=||,具體是什麼不知道可以百度一下。循環結束後所有非0的格子均爲必勝態填1。


【代碼】

#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<algorithm>
using namespace std;
#define LL long long
int sg[1010][1010][5];
vector<int> v[5];
int kx[3]={0,-1,-1},ky[3]={-1,0,-1};
int nx[2]={-1,-2},ny[2]={-2,-1};
int re[1010];
void init(){
    memset(sg,-1,sizeof(sg));
    for(int i=1;i<=4;++i)
        sg[0][0][i]=0;
    int tmp=0;
    for(int i=1;i<=1000 && tmp<=1000;++i){
        if(re[i]){
            tmp++;
            continue;
        }
        tmp+=2;
        re[i]=re[tmp]=1;
        sg[i][tmp][4]=sg[tmp][i][4]=0;
    }
    for(int i=0;i<=1000;++i)
        for(int j=0;j<=1000;++j){
            if(i==0 && j==0)
                continue;
            int tmp=1;
            for(int k=0;k<3;++k)
                if(i+kx[k]>=0 && j+ky[k]>=0 && sg[i+kx[k]][j+ky[k]][1]!=-1)
                    tmp&=sg[i+kx[k]][j+ky[k]][1];
            sg[i][j][1]=(!tmp);
            if(i==j)
                sg[i][j][2]=0;
            else
                sg[i][j][2]=1;
            tmp=1;
            int fla=0,fla2=0;
            for(int k=0;k<2;++k)
                if(i+nx[k]>=0 && j+ny[k]>=0){
                    if(sg[i+nx[k]][j+ny[k]][3]!=-1){
                        tmp&=sg[i+nx[k]][j+ny[k]][3];
                        fla=1;
                    }
                    else
                        fla2=1;
                }
            if(fla){
                if(tmp){
                    if(fla2)
                        sg[i][j][3]=-1;
                    else
                        sg[i][j][3]=0;
                }
                else
                    sg[i][j][3]=1;
            }
            if(sg[i][j][4]!=0)
                sg[i][j][4]=1;
        }
}
int main(){
    init();
    int T,t,n,m;
    cin>>T;
    while(T--){
        scanf("%d %d %d",&t,&n,&m);
        n--;
        m--;
        if(sg[n][m][t]==1){
            cout<<"B\n";
            continue;
        }
        if(sg[n][m][t]==0){
            cout<<"G\n";
            continue;
        }
        cout<<"D\n";
    }
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章