POJ_1657:棋盘上的距离

1、问题描述:

Description

国际象棋的棋盘是黑白相间的8 * 8的方格,棋子放在格子中间。如下图所示: 

王、后、车、象的走子规则如下: 
  • 王:横、直、斜都可以走,但每步限走一格。 
  • 后:横、直、斜都可以走,每步格数不受限制。 
  • 车:横、竖均可以走,不能斜走,格数不限。 
  • 象:只能斜走,格数不限。


写一个程序,给定起始位置和目标位置,计算王、后、车、象从起始位置走到目标位置所需的最少步数。 

Input

第一行是测试数据的组数t(0 <= t <= 20)。以下每行是一组测试数据,每组包括棋盘上的两个位置,第一个是起始位置,第二个是目标位置。位置用"字母-数字"的形式表示,字母从"a"到"h",数字从"1"到"8"。 

Output

对输入的每组测试数据,输出王、后、车、象所需的最少步数。如果无法到达,就输出"Inf".

Sample Input

2
a1 c3
f5 f8

Sample Output

2 1 2 1
3 1 1 Inf

二、解题思路自我理解:

①、本题的关键在于一个是理解清楚各中棋子的移动规则,第二个是恰当的表示起始位置和重点位置的表示,设起点和终点位置在水平方向上的距离是X,起点和终点在竖直方向上的距离是y。根据题目输入输出要求,用字符串数组储存起点和终点位置,char begin[5]、 char end[5]分别储存的是起点和终点的位置,显然起点和终点在水平方向的距离x=abs(begin[0]-end[0]), 起点和终点在竖直方向的距离是y=abs(begin[1]-end[1]);

②、对于王来说,横竖斜都可以走,但只能走一步,所以王的最少步子走法应该是先走一个等腰三角形的斜边(等腰边长是xy中两者小者),然后直线走abs(x-y),对于在起点和终点的同一水平线或同一竖直线,可以理解为等腰三角形的等腰边为0即可; (min(x,y) + abs(x-y) = max(x,y) )

③、对于后来说,由于每步格子不限,如果起点和终点在同一条水平线(y=0)或者在同一竖直线上(x=0)或在等腰三角形斜边上(x=y),那么一步到位,如果不是,那么就是先一步走等腰三角形斜边,第二步走xy差值;

④、对于车来说,不能斜走但横竖步数不限,那么要么是一步(起点终点处于同一水平线或竖直线),要么两步(先横后竖或者先竖后横);

⑤、对于象来说,只能斜走,那么存在不可达情况。斜走的一个重要特性是走的前后两点其在棋盘上的横纵坐标差的奇偶性不会改变,意思是说只要两点横纵坐标差同为奇数或同为偶数,就可达,否则不可达(Inf);对于可达情况的步数的确定,如果起点和终点在一个等腰三角形的上(横坐标差x = 纵坐标差y),那么就是一步。否则就是两步。

⑥、由于在第⑤点中涉及到到了每个坐标的横纵差(abs(begain[0]-begain[1])、abs(end[0]-end[1])),前面只定义了起点终点坐标的的相对横纵差(x=abs(begin[0]-end[0])、y=abs(begin[1]-end[1])),一种比较低效的编码方法是: 不可达情况即if( (abs(begin[0]-begin[1])%2==0&&abs(end[0]-end[1])%2!=0) ||(abs(begin[0]-begin[1])%2!=0&&abs(end[0]-end[1])%2==0)  printf("Inf\n"); 一种比较好的编码方法是 if(abs(x-y)%2 !=0) printf("Inf\n"); ---- 两点横纵坐标差同为奇数或同为偶数,根据同奇偶相减为偶的原则即 abs【abs(begain[0]-begain[1]) - abs(end[0]-end[1])】为偶数即可,【不理解前面的abs(x-y)就为何等价于后面的abs嵌套,直接用后面的abs嵌套,直观】。


三、源码:

#include <stdio.h>
#include <stdlib.h>

int main()
{
	int nCasses, i; //nCasses表示测试数据个数
	scanf("%d", &nCasses);
	for(i=0; i<nCasses; i++)
	{
		char begin[5], end[5];
		scanf("%s %s", begin, end);
		int x, y;
		x = abs(begin[0] - end[0]);
		y = abs(begin[1] - end[1]);
		if( x==0 && y==0) printf("0 0 0 0\n");
		else
		{
			if(x<y) printf("%d", y);
			else printf("%d", x); //王的步子情况,棋盘中等腰三角形斜边和直边的格子数是一样的,min(x,y) + abs(x-y) = max(x,y)
			if(x==y || x==0 || y==0) printf(" 1");
			else printf(" 2");//后的步子情况
			if(x==0 || y==0) printf(" 1");
			else printf(" 2");//车的步子情况
			if(abs(x-y)%2 !=0) printf("Inf\n");
			else if(x==y) printf(" 1\n");
			else printf(" 2\n");//象的步子情况
		}
	}
	system("pasue");
	return 0;
}
			 
	

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值