题目链接:http://codeforces.com/problemset/problem/370/A
题目意思:根据rook(每次可以移动垂直或水平的任意步数(>=1)),bishop(每次可以移动对角线上的任意步数(>=1))和king(每次垂直、水平或对角线的一步(=1))的走法,给出起始位置和结束位置。求出这三种棋子分别从起始位置走到最终位置的最少步数。
rook bishop king
首先,先解释下面所说的直线和斜线。
直线:是坐标轴上与x轴平行或与y轴平行的情况的直线。
斜线:图中bishop能走的斜线(能走到坐标点的格子),不是一般的那种斜线(可能走的过程中走不到整数的格子的)
rook是最容易的,如果起始位置和最终位置在同一直线,那么只需要一步即可,否则是两步。
比较麻烦的是bishop,一开始很天真地以为,如果不是斜线的那种情况,bishop就无法到达最终位置。其实处于同一直线也是可以的。如果是(3,1)到(5,1),可以通过(4,2)这个桥梁,到达终点。还有,一般斜线的情况,例如(3,1)到(4,6),可以经过(6,4)。
还是以(3,1)到(4,6)这个例子来说明我的解决办法
考虑到棋盘的特殊性,分别以起点和终点画一条斜线(假设对应为k1和k2),两条斜线必须满足斜率是不同的,满足k1 * k2 = -1),求出两条斜线的交点,判断是否为整数。(注意,即使这个交点超出棋盘范围之外也没有所谓,因为它可以通过另外一个对称点(以黄色标记)来到达目的地)。可能大家会觉得求出交点很麻烦,但是其实也不是很难。由于已经知道斜线上的斜率和交点,那么方程就确定了)
K1 = -1, 方程为: y = -x + 4 (y1 = k1*x1 + b1)
K2 = 1, 方程为: y = x + 2 (y2 = k2*x2 + b2)
联立方程 y = (4 + 2)/ 2 = 2
求出的y是整数,说明交点在格子上,其实得出的交点是什么不重要,关键是判断是否为整数,是则bishop的步数为2,否则不可达,为0。抽象出来,b1 = x1 + y1,b2 = y2 - x2,交点y = (b1+b2)/2。
至此,bishop解决了,还有最后的king,这里不详细说明,不过本人觉得也是要考虑清楚的。
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cmath> int main()
{
int r1, c1, r2, c2, t1, t2, flag1, flag2;
while (scanf("%d%d%d%d", &r1, &c1, &r2, &c2) != EOF)
{
// rook
flag2 = ;
if ((r1 == r2 && c1 != c2) || (c1 == c2 && r1 != r2))
{
flag2 = ;
printf("1 ");
}
else
printf("2 ");
// bishop
flag1 = ;
if (abs(r1-r2) == abs(c1-c2))
{
printf("1 ");
flag1 = ;
}
else
{
t1 = r1 + c1;
if (r2 > c2)
t2 = r2 - c2;
else
t2 = c2 - r2;
if ((t1 + t2) % == )
printf("2 ");
else
printf("0 ");
}
// king
if (flag2) //一条直线
printf("%d\n", abs(r1-r2) + abs(c1-c2));
else if (flag1) //一条斜线
printf("%d\n", abs(r1-r2));
else if (abs(r1-r2) < abs(c1-c2))
printf("%d\n", abs(c1-c2));
else
printf("%d\n", abs(r1-r2));
}
return ;
}