POJ 1657 Distance on Chessboard

题目描述:
    在国际象棋棋盘上给出起点 a 和终点 b,分别求出 王、后、车、象 四种棋子从 a 到 b 所需要的步数;
    王、后、车、象的走法:
                         王:八个方向都可以走,每步只能走一格;
                         后:八个方向都可以走,每步没有格数限制;
                         车:只能走直线,每步没有格数限制;

                         象:只能走斜线,每步没有格数限制。

 

算法描述:
    根据王、后、车、象的走法可以得出如下结论:


    王:由于王每次只能走一格,王斜着移动时每步相当于横向移一格再竖向移动一格,当起点和终点不在同一水平或竖直线上时,最优方法是先从起点到终点方向斜着移动,直到移动到和终点在同一水平或竖直线上,然后再水平或竖直移动,斜着移动的步数等于起点和终点横纵坐标之差的绝对值中较大的一个,因此移动的步数就等效成横纵坐标差较大的一个。显然对于起点和终点在同一水平或竖直线上的情况该结论也成立。 
    
    后:由于后没有格数限制,也没有方向限制,因此如果起点和终点在同一水平或竖直或斜线上,只需一步就可以完成,否则需要两步即可完成,不存在其他情况。
    
    车:车和后的区别只是不能沿斜线方向走,因此,当起点和终点在同一水平或竖直线上时,需要一步即可完成,其他情况则需要两步。
    
    象:由于象只能斜行,因此对于象来说,棋盘上有一般的格子是无法达到的。根据棋盘坐标可以得出结论:如果起点的横纵坐标之和与终点的横纵坐标之和具有相同的奇偶性,那么可以从起点到达终点,否则就不可以。对于可以到达的情况,如果起点和终点在同一斜线上,则一步就可到达,否则需要两步。
 

    特殊情况:如果给出的起点和终点重合,直接输出 0 即可,不能使用上面的结论。


Code:

#include <iostream>
#include <cstdio>
using namespace std;
struct node
{
    int x;
    int y;
};
int deg_abs( int x )
{
    return x >= 0 ? x : -x;
}
int Queen( node a, node b ) //后
{
    if( a.x == b.x && a.y == b.y )
        return 0;
    else if( a.x == b.x || a.y == b.y )
        return 1;
    else if( deg_abs( ( b.y - a.y ) * 1.0 / ( b.x - a.x ) ) == 1.0 )
        return 1;
    else
        return 2;
}
int King( node a, node b ) //王
{
    if( a.x == b.x && a.y == b.y )
        return 0;
    return max( deg_abs( a.x - b.x ), deg_abs( a.y - b.y ) );
}
int Rook( node a, node b ) //车
{
    if( a.x == b.x && a.y == b.y )
        return 0;
    else if( a.x == b.x || a.y == b.y )
        return 1;
    else
        return 2;
}
int Bishop( node a, node b ) //象
{
    if( a.x == b.x && a.y == b.y )
        return 0;
    else if( ( a.x + a.y ) % 2 != ( b.x + b.y ) % 2 )
        return -1;
    else if( deg_abs( ( b.y - a.y ) * 1.0 / ( b.x - a.x ) ) == 1.0 )
        return 1;
    else
        return 2;
}
int main()
{
    char st[3], ed[3];
    int n;
    scanf( "%d", &n );
    while( n-- )
    {
        scanf( "%s%s", st, ed );
        node a, b;
        a.x = (int)( st[0] - 'a' + 1 );
        a.y = (int)( st[1] - '0' );
        b.x = (int)( ed[0] - 'a' + 1 );
        b.y = (int)( ed[1] - '0' );
        printf( "%d ", King( a, b ) );
        printf( "%d ", Queen( a, b ) );
        printf( "%d ", Rook( a, b ) );
        if( Bishop( a, b ) == -1 )
            printf( "Inf\n" );
        else
            printf( "%d\n", Bishop( a, b ) );
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值