給定騎士在棋盤上的 初始 位置(一個2進制矩陣 0 表示空 1 表示有障礙物),找到到達 終點 的最短路線,傳回路線的長度。如果騎士不能到達則傳回 -1 。
起點跟終點必定為空.
騎士不能碰到障礙物.
路徑長度指騎士走的步數.
線上評測位址:
LintCode 領扣
說明
如果騎士的位置為 (x,y),他下一步可以到達以下這些位置:
(x + 1, y + 2)
(x + 1, y - 2)
(x - 1, y + 2)
(x - 1, y - 2)
(x + 2, y + 1)
(x + 2, y - 1)
(x - 2, y + 1)
(x - 2, y - 1)
樣例
例1:
輸入:
[[0,0,0],
[0,0,0],
[0,0,0]]
source = [2, 0] destination = [2, 2]
輸出: 2
解釋:
[2,0]->[0,1]->[2,2]
例2:
[[0,1,0],
[0,0,1],
輸出:-1
算法:BFS
樸素BFS搜搜最短路,BFS概括來說就是像雷達一樣,一層一層進行尋找目标點。當找到目标點後進行回溯。進而找到最佳路徑。也就是說每走一步都要找到到達該點的最短的路徑,最終得到到達所有點的最短路徑,這題每一次的下一步做了規定,按照日字形跳到下一步。
根據下一跳位置建立方向數組
dx=[1, 1, 2, 2, -1, -1, -2, -2]
dy=[2, -2, 1, -1, 2, -2, 1, -1]
周遊八個方向,進行搜尋
用grid數組标注是否通路過某點
注意判斷下一跳的位置是否越界
複雜度分析
時間複雜度O(n*m)
最多跑一邊圖 n為圖的行數,m為圖的列數,最多跑一邊圖,即n*m
空間複雜度O(n*m)
所有點的資訊 n為圖的行數,m為圖的列數
public class Solution {
/**
* @param grid: a chessboard included 0 (false) and 1 (true)
* @param source: a point
* @param destination: a point
* @return: the shortest path
*/
public int shortestPath(boolean[][] grid, Point source, Point destination) {
int n = grid.length,m = grid[0].length;
if (n == 0 || m == 0) {
return -1;
}
int[] dx = {1, 1, 2, 2, -1, -1, -2, -2};
int[] dy = {2, -2, 1, -1, 2, -2, 1, -1};
Queue<Point> queue = new LinkedList<>();
queue.offer(source);
grid[source.x][source.y] = true;
int ans = 0;
while (!queue.isEmpty()) {
int size = queue.size();
for (int k = 0; k < size; k++) {
Point cur = queue.poll();
//到達終點,傳回距離
if (cur.x == destination.x && cur.y == destination.y) {
return ans;
}
for (int i = 0; i < 8; i++) {
Point next = new Point (
cur.x + dx[i],
cur.y + dy[i]
);
//判斷下一條可否到達
if (is_in_bound(next,n,m) && grid[next.x][next.y] == false) {
queue.offer(next);
grid[next.x][next.y] = true;
}
}
}
ans++;
}
return -1;
}
//判斷是否越界
private boolean is_in_bound(Point next,int n,int m) {
return 0 <= next.x && next.x < n && 0 <= next.y && next.y < m;
}
}
更多題解參考:
九章算法官網