【Leetcode 每日一题】3001. 捕获黑皇后需要的最少移动次数
问题背景
现有一个下标从
1
1
1 开始的
8
×
8
8 \times 8
8×8 棋盘,上面有
3
3
3 枚棋子。
给你
6
6
6 个整数
a
a
a、
b
b
b、
c
c
c、
d
d
d、
e
e
e 和
f
f
f,其中:
(
a
,
b
)
(a, b)
(a,b) 表示白色车的位置。
(
c
,
d
)
(c, d)
(c,d) 表示白色象的位置。
(
e
,
f
)
(e, f)
(e,f) 表示黑皇后的位置。
假定你只能移动白色棋子,返回捕获黑皇后所需的最少移动次数。
请注意:
- 车可以向垂直或水平方向移动任意数量的格子,但不能跳过其他棋子。
- 象可以沿对角线方向移动任意数量的格子,但不能跳过其他棋子。
- 如果车或象能移向皇后所在的格子,则认为它们可以捕获皇后。
- 皇后不能移动。
数据约束
- 1 ≤ a , b , c , d , e , f ≤ 8 1 \le a, b, c, d, e, f \le 8 1≤a,b,c,d,e,f≤8
- 两枚棋子不会同时出现在同一个格子上
解题过程
由于皇后不能移动,所以其实最多只要移动两次就能解决:
- 如果没有被阻挡,直接移动车或者象,只需要一次操作。
- 如果其中一个棋子能够捕获,但是被另一个棋子阻挡了,那么移开阻挡的棋子,只需要两次操作。
- 如果都不在将要捕获的状态,无论是否被阻挡,只需要移动两次车(先同行再同列,或者先同列再同行)即可。
判断是否阻挡,实际上是判断某个棋子是否在另外两个棋子对应线路的中间,有两种方案,比较距离或者判断符号。
具体实现
比较距离
class Solution {
public int minMovesToCaptureTheQueen(int a, int b, int c, int d, int e, int f) {
if (a == e && (c != e || !between(b, d, f)) ||
b == f && (d != f || !between(a, c, e)) ||
c + d == e + f && (a + b != e + f || !between(c, a, e)) ||
c - d == e - f && (a - b != e - f || !between(c, a, e))) {
return 1;
}
return 2;
}
private boolean between(int l, int m, int r) {
return Math.min(l, r) < m && m < Math.max(l, r);
}
}
判断符号
class Solution {
public int minMovesToCaptureTheQueen(int a, int b, int c, int d, int e, int f) {
if (a == e && (c != e || (d - b) * (d - f) > 0) ||
b == f && (d != f || (c - a) * (c - e) > 0) ||
c + d == e + f && (a + b != e + f || (a - c) * (a - e) > 0) ||
c - d == e - f && (a - b != e - f || (a - c) * (a - e) > 0)) {
return 1;
}
return 2;
}
}