1. 程式人生 > 實用技巧 >1197. Minimum Knight Moves

1197. Minimum Knight Moves

In an infinite chess board with coordinates from -infinity to +infinity, you have a knight at square[0, 0].

A knight has 8 possible moves it can make, as illustrated below. Each move is two squares in a cardinal direction, then one square in an orthogonal direction.


Return the minimum number of steps needed to move the knight to the square[x, y]. It is guaranteed the answer exists.

求最短路徑,標準的bfs廣度優先搜尋題目。本題如果沒有棋盤無限大這個條件,那麼完完全全是一道簡單的bfs模板題型。因此考慮到棋盤範圍的因素,普通的bfs肯定會超時,所以我們應該首先確定下來從起點到終點的合理範圍有哪些。顯而易見,如果朝著終點越來越遠的方向走肯定是浪費計算時間的部分,如果簡單來為棋盤來劃定一下界限,起點和終點兩個座標(x1,y1), (x2,y2)圍成的四邊形應該是相對合理的範圍。但是考慮到如果兩個點在一條直線上,或者兩點間的距離過近而無法完成日字跳躍的情況,我們可以將劃定的棋盤範圍四周分別擴大2格即可。

此外,為了方便,我們可以將起點和終點平移到正數座標範圍內。舉個例子,比如:

int x = -5; // 終點x int y = -3; // 終點y int startX = 0; // 起點x int starty = 0; // 起點y

先將終點移動到(0, 0),相應的起點會被移動到(5, 3)。此外,要考慮到上面提到的擴大2格的操作,因此,終點T應該是(2, 2),起點S則是(7, 5)。相應的棋盤範圍則是(0, 0) 到(9, 7)之間的範圍,即下圖藍色區域。

確定了棋盤範圍之後,剩下的就是簡單的常規bfs操作了。

 1 class Solution {
 2     public int minKnightMoves(int x, int y) {
 3
// 定義bfs可以走的八個方向 4 int[][] directions = { { -1, -2 }, { 1, -2 }, { 2, -1 }, { 2, 1 }, { 1, 2 }, { -1, 2 }, { -2, 1 }, { -2, -1 } }; 5 int startX = 0, startY = 0; // 起始座標 6 if (x < 0) { // 如果終點橫座標小於0 7 // 起點橫座標與終點橫座標同時移動x個單位 8 startX = -x; 9 x = 0; 10 } 11 if (y < 0) { // 如果終點縱座標小於0 12 // 起點縱座標與終點縱座標同時移動y個單位 13 startY = -y; 14 y = 0; 15 } 16 // 為了將棋盤範圍四周分別擴大2格,將起點和終點座標再分別平移2個單位 17 startX += 2; 18 startY += 2; 19 x += 2; 20 y += 2; 21 // 棋盤的右邊界為起點和終點較大x值加2 22 int right = Math.max(startX, x) + 2; 23 // 棋盤的下邊界為起點和終點較大y值加2 24 int bottom = Math.max(startY, y) + 2; 25 // 以下是常規bfs套路程式碼 26 Queue<int[]> q = new LinkedList<>(); 27 q.offer(new int[] { startX, startY }); 28 boolean[][] visited = new boolean[right + 1][bottom + 1]; 29 visited[startX][startY] = true; 30 31 int res = 0; 32 while (q.size() > 0) { 33 int size = q.size(); 34 while (size-- > 0) { 35 int[] current = q.poll(); 36 if (current[0] == x & current[1] == y) { 37 return res; 38 } 39 for (int[] direction : directions) { 40 int nextX = current[0] + direction[0]; 41 int nextY = current[1] + direction[1]; 42 if (nextX <= right && nextX >= 0 && nextY <= bottom && nextY >= 0 && !visited[nextX][nextY]) { 43 visited[nextX][nextY] = true; 44 q.offer(new int[] { nextX, nextY }); 45 } 46 } 47 } 48 res++; 49 } 50 return -1; 51 } 52 }

From:https://leetcode.jp/leetcode-1197-minimum-knight-moves-%e8%a7%a3%e9%a2%98%e6%80%9d%e8%b7%af%e5%88%86%e6%9e%90/