HDU 5754 Life Winner Bo 2016 多校合练 Contest 3

本文探讨了一种棋盘游戏,玩家需使用四种不同棋子(国王、皇后、马和车)从起点移动到终点的游戏策略。通过对每种棋子移动规则的分析,总结出了在最优策略下谁将赢得游戏的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


Problem Description
Bo is a "Life Winner".He likes playing chessboard games with his girlfriend G.

The size of the chessboard is N×M .The top left corner is numbered (1,1) and the lower right corner is numberd (N,M) .

For each game,Bo and G take turns moving a chesspiece(Bo first).At first,the chesspiece is located at (1,1) .And the winner is the person who first moves the chesspiece to (N,M) .At one point,if the chess can't be moved and it isn't located at (N,M) ,they end in a draw.

In general,the chesspiece can only be moved right or down.Formally,suppose it is located at (x,y) ,it can be moved to the next point (x,y) only if xx and yy .Also it can't be moved to the outside of chessboard.

Besides,There are four kinds of chess(They have movement rules respectively).

1.king.

2.rook(castle).

3.knight.

4.queen.

(The movement rule is as same as the chess.)

For each type of chess,you should find out that who will win the game if they both play in an optimal strategy.

Print the winner's name("B" or "G") or "D" if nobody wins the game.
 

Input
In the first line,there is a number T as a case number.

In the next T lines,there are three numbers type, N and M .

"type" means the kind of the chess.

T1000,2N,M1000,1type4
 

Output
For each question,print the answer.
 

Sample Input
  
4 1 5 5 2 5 5 3 5 5 4 5 5
 

Sample Output
  
G G D B
 



题意:
题意很简单,就是四个棋子国王,皇后,马和车,问你从(1,1)点谁能先下到(n,m)点。
首先是国王:国王可以直走和斜走一格。那么与他相邻的格子就是(1,2)(2,2)(2,1)为先手点,可以递归,求只能被先手点走一次走到的点为后手点。这样得出规律当n,m都是级数为后手点。
其次是车:车可以走直线,那么(1,n)与(n,1)都是先手点,那么(2,2)必为后手点。这样通过递归思想,所有(n,n)点,都是后手点。
然后是马。通过达标可以发现,马的位置是固定点,分成先手行与后手行。有一个坑就是如果这个点虽然可以走到且甲赢,但是如果乙不想让你走到,在某些点是可以做到的。这样就发现,只有在角平分线附近的一个或两个点是不受对方影响的两个点。这就得出先手点与后手点。
最后是王后,通过打表,每次遍历先手点,求i+j最小的点设置成后手点,再次遍历,得到王后表。
这个题只让打一个表。

#include<iostream>
#include<iostream>
#include<string.h>
#include<algorithm>
#include<map>
using namespace std;
int Knight[1010][1010];

void Build( int x, int y )
{
    if( x > 1000 || y > 1000 )
        return;
    int X, Y;
    bool fa = 0;
    int min = 2000;
    for( int i = x + 1; i < 1001; i++ )
    {
        for( int j = y + 1; j < 1001; j++ )
        {
            if( Knight[i][j] == 0 )
            {
                if( min > i + j )
                {
                    X = i;
                    Y = j;
                    min = i + j;
                    fa = 1;
                    break;
                }
            }
        }
    }
    if( !fa )
        return;
    Knight[X][Y] = 2;
    Knight[Y][X] = 2;
    for( int i = X + 1; i < 1001; i++ )
    {
        Knight[i][Y] = 1;
        Knight[Y][i] = 1;
    }
    for( int i = Y + 1; i < 1001; i++ )
    {
        Knight[X][i] = 1;
        Knight[i][X] = 1;
    }
    for( int i = 1; i+X < 1001 && i+Y < 1001; i++ )
    {
        Knight[X+i][Y+i] = 1;
        Knight[Y+i][X+i] = 1;
    }
    Build( X, Y );
    Build( Y, X );
}

int main()
{
    int T, N, M;
    int type;
    
    memset( Knight, false, sizeof(Knight) );
    Build( 0, 0 );

    /*for( int i = 1; i < 11; i++ )
    {
        for( int j = 1; j < 11; j++ )
            cout << Knight[i][j] << " ";
        cout << endl;
    }*/

    cin >> T;

    while( T-- )
    {
        cin >> type >> N >> M;

        if( type == 1 )
        {
            if( (M + N) % 2 == 0 && (N & 1) && (M & 1) )
                cout << "G" << endl;
            else
                cout << "B" << endl;
        }
        else if( type == 2 )
        {
            if( N == M )
                cout << "G" << endl;
            else
                cout << "B" << endl;
        }
        else if( type == 4 )
        {
            if( Knight[N][M] == 2 )
                cout << "G" << endl;
            else
                cout << "B" << endl;
        }
        else
        {
            if( N < M )
            {
                int C = N;
                N = M;
                M = C;
            }
            if( (N + M - 2) % 3 != 0 )
                cout << "D" << endl;
            else if( (N-M)>1 )
                cout << "D" << endl;
            else
            {
                int x = N + M - 2;
                if( x % 6 == 0 )
                    cout << "G" << endl;
                else
                    cout << "B" << endl;
            }
        }
    }

    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值