问题背景
现有一个下标从 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;}
}