目标
现有一个下标从 1 开始的 8 x 8 棋盘,上面有 3 枚棋子。
给你 6 个整数 a 、b 、c 、d 、e 和 f ,其中:
- (a, b) 表示白色车的位置。
- (c, d) 表示白色象的位置。
- (e, f) 表示黑皇后的位置。
假定你只能移动白色棋子,返回捕获黑皇后所需的最少移动次数。
请注意:
- 车可以向垂直或水平方向移动任意数量的格子,但不能跳过其他棋子。
- 象可以沿对角线方向移动任意数量的格子,但不能跳过其他棋子。
- 如果车或象能移向皇后所在的格子,则认为它们可以捕获皇后。
- 皇后不能移动。
示例 1:
输入:a = 1, b = 1, c = 8, d = 8, e = 2, f = 3
输出:2
解释:将白色车先移动到 (1, 3) ,然后移动到 (2, 3) 来捕获黑皇后,共需移动 2 次。
由于起始时没有任何棋子正在攻击黑皇后,要想捕获黑皇后,移动次数不可能少于 2 次。
示例 2:
输入:a = 5, b = 3, c = 3, d = 4, e = 5, f = 2
输出:1
解释:可以通过以下任一方式移动 1 次捕获黑皇后:
- 将白色车移动到 (5, 2) 。
- 将白色象移动到 (5, 2) 。
说明:
- 1 <= a, b, c, d, e, f <= 8
- 两枚棋子不会同时出现在同一个格子上。
思路
有一个 8 x 8 的棋盘,上面有车、象、皇后三个棋子。其中车和象是白色,皇后是黑色。车走横线与竖线,象走斜线,皇后固定不动。问白棋捕获黑皇后所需的最小移动次数,所谓捕获指任意白棋走到黑皇后所在的位置。注意,沿着某一方向移动多个格子算一步。
当我们移动一个白棋的时候另一个白棋是不动的,所以就可能存在一个白棋被另一个白棋挡住的情况。如果不考虑碰撞,白棋捕获黑皇后最多走两步,并且有两种走法,对于车来说可以先走到同一行或者同一列。这时如果另一个白棋出现在其中一条路径上,我们只需选另一条路径即可,最多走两步。因此白棋阻挡只会对初始时可以一步捕获的情况产生影响,这时我们只需要将阻挡的棋子移开,然后另一个棋子可以一步直达,还是两步。
根据上面的分析,如果某个白棋可以直接捕获黑皇后(路径上没有阻挡),那么只需要移动一次,否则需要移动两次。
题解中给出了另一种写法来判断是否产生阻挡的情况,如果 (m − l) * (m − r) > 0
,那么整数 m 不在整数 l 和 r 之间。如果在它们之间,符号一定相异,l 与 r 换位置也不影响,这样无需比较二者的最大最小值。
代码
/**
* @date 2024-12-05 10:06
*/
public class MinMovesToCaptureTheQueen3001 {
public int minMovesToCaptureTheQueen(int a, int b, int c, int d, int e, int f) {
// 车与皇后在同一行,象没有在同一行,或者在同一行却不在二者之间
if (a == e && (a != c || d < Math.min(b, f) || d > Math.max(b, f))) {
return 1;
}
// 车与皇后在同一列,象没有在同一列,或者在同一列却不在二者之间
if (b == f && (b != d || c < Math.min(a, e) || c > Math.max(a, e))) {
return 1;
}
// 象与皇后在同一斜线,车没有在同一斜线,或者在同一斜线却不在二者之间
if (c + d == e + f && (a + b != c + d || a < Math.min(c, e) || a > Math.max(c, e))) {
return 1;
}
if (c - d == e - f && (a - b != c - d || a < Math.min(c, e) || a > Math.max(c, e))) {
return 1;
}
return 2;
}
}