思路就是用BFS一层一层搜,但要记得搜过的点要标识为1,不然好像会陷入死循环。因为很容易走成环。
记得每次从queue中取出节点就要判断是不是终点,而不是放在下面一个8方向遍历的循环里面判断。
代码如下:
/**
* Definition for a point.
* struct Point {
* int x;
* int y;
* Point() : x(0), y(0) {}
* Point(int a, int b) : x(a), y(b) {}
* };
*/
class Solution {
public:
/**
* @param grid: a chessboard included 0 (false) and 1 (true)
* @param source: a point
* @param destination: a point
* @return: the shortest path
*/
bool inbound(vector<vector<bool>> &grid, Point p) {
return (p.x>=0 && p.x<grid.size() && p.y>=0 && p.y<grid[0].size()) && !grid[p.x][p.y];
}
int shortestPath(vector<vector<bool>> &grid, Point &source, Point &destination) {
vector<int> dirX={1,1,-1,-1,2,2,-2,-2};
vector<int> dirY={2,-2,2,-2,1,-1,1,-1};
queue<Point> q;
q.push(source);
int steps=0;
while(!q.empty()) {
int qSize = q.size();
for (int i=0; i<qSize; ++i) {
Point p=q.front();
q.pop();
if ((p.x==destination.x) && (p.y==destination.y))
return steps;
for (int j=0; j<8; ++j) {
Point neighbor=Point(p.x+dirX[j], p.y+dirY[j]);
if (inbound(grid, neighbor)) {
q.push(neighbor);
grid[neighbor.x][neighbor.y]=true;
}
}
}
steps++;
}
return -1;
}
};
代码同步在
https://github.com/luqian2017/Algorithm
优化:双向BFS。时间复杂度优化到根号的级别。
/**
* Definition for a point.
* struct Point {
* int x;
* int y;
* Point() : x(0), y(0) {}
* Point(int a, int b) : x(a), y(b) {}
* };
*/
class Solution {
public:
/**
* @param grid: a chessboard included 0 (false) and 1 (true)
* @param source: a point
* @param destination: a point
* @return: the shortest path
*/
int shortestPath(vector<vector<bool>> &grid, Point source, Point destination) {
int row_size = grid.size();
if (row_size == 0) return -1;
int col_size = grid[0].size();
if (col_size == 0) return -1;
if (source.x == destination.x && source.y == destination.y) return 0;
int dx[8] = {1, 1, -1, -1, 2, 2, -2, -2};
int dy[8] = {2, -2, 2, -2, 1, -1, 1, -1};
int forward_steps = 0, backward_steps = 0;
queue<Point> forward_queue, backward_queue;
vector<vector<bool>> forward_visited(row_size, vector<bool>(col_size, false));
vector<vector<bool>> backward_visited(row_size, vector<bool>(col_size, false));
forward_queue.push(source);
forward_visited[source.x][source.y] = true;
backward_queue.push(destination);
backward_visited[destination.x][destination.y] = true;
while (!forward_queue.empty() && !backward_queue.empty()) {
int forwardQSize = forward_queue.size();
for (int i = 0; i < forwardQSize; i++) {
Point frontNode = forward_queue.front();
forward_queue.pop();
for (int j = 0; j < 8; j++) {
int newX = frontNode.x + dx[j];
int newY = frontNode.y + dy[j];
Point newNode(newX, newY);
if (newX < 0 || newX >= row_size ||
newY < 0 || newY >= col_size ||
grid[newX][newY] == 1 ||
forward_visited[newX][newY]) continue;
if (backward_visited[newX][newY]) {
return forward_steps + backward_steps + 1;
}
forward_queue.push(newNode);
forward_visited[newX][newY] = true;
}
}
forward_steps++;
int backwardQSize = backward_queue.size();
for (int i = 0; i < backwardQSize; i++) {
Point frontNode = backward_queue.front();
backward_queue.pop();
for (int j = 0; j < 8; j++) {
int newX = frontNode.x + dx[j];
int newY = frontNode.y + dy[j];
Point newNode(newX, newY);
if (newX < 0 || newX >= row_size ||
newY < 0 || newY >= col_size ||
grid[newX][newY] == 1 ||
backward_visited[newX][newY]) continue;
if (forward_visited[newX][newY]) {
return forward_steps + backward_steps + 1;
}
backward_queue.push(newNode);
backward_visited[newX][newY] = true;
}
}
backward_steps++;
}
return -1;
}
};
稍微改了一下,不需要前后两个step,一个就够了。
/**
* Definition for a point.
* struct Point {
* int x;
* int y;
* Point() : x(0), y(0) {}
* Point(int a, int b) : x(a), y(b) {}
* };
*/
class Solution {
public:
/**
* @param grid: a chessboard included 0 (false) and 1 (true)
* @param source: a point
* @param destination: a point
* @return: the shortest path
*/
int shortestPath(vector<vector<bool>> &grid, Point source, Point destination) {
int row_size = grid.size();
if (row_size == 0) return -1;
int col_size = grid[0].size();
if (col_size == 0) return -1;
if (source.x == destination.x && source.y == destination.y) return 0;
int dx[8] = {1, 1, -1, -1, 2, 2, -2, -2};
int dy[8] = {2, -2, 2, -2, 1, -1, 1, -1};
//int forward_steps = 0, backward_steps = 0;
int steps = 0;
queue<Point> forward_queue, backward_queue;
vector<vector<bool>> forward_visited(row_size, vector<bool>(col_size, false));
vector<vector<bool>> backward_visited(row_size, vector<bool>(col_size, false));
forward_queue.push(source);
forward_visited[source.x][source.y] = true;
backward_queue.push(destination);
backward_visited[destination.x][destination.y] = true;
while (!forward_queue.empty() && !backward_queue.empty()) {
int forwardQSize = forward_queue.size();
for (int i = 0; i < forwardQSize; i++) {
Point frontNode = forward_queue.front();
forward_queue.pop();
if (backward_visited[frontNode.x][frontNode.y]) return steps;
for (int j = 0; j < 8; j++) {
int newX = frontNode.x + dx[j];
int newY = frontNode.y + dy[j];
Point newNode(newX, newY);
if (newX < 0 || newX >= row_size ||
newY < 0 || newY >= col_size ||
grid[newX][newY] == 1 ||
forward_visited[newX][newY]) continue;
//if (backward_visited[newX][newY]) return steps;
//return forward_steps + backward_steps + 1;
forward_queue.push(newNode);
forward_visited[newX][newY] = true;
}
}
steps++;
int backwardQSize = backward_queue.size();
for (int i = 0; i < backwardQSize; i++) {
Point frontNode = backward_queue.front();
backward_queue.pop();
if (forward_visited[frontNode.x][frontNode.y]) return steps;
for (int j = 0; j < 8; j++) {
int newX = frontNode.x + dx[j];
int newY = frontNode.y + dy[j];
Point newNode(newX, newY);
if (newX < 0 || newX >= row_size ||
newY < 0 || newY >= col_size ||
grid[newX][newY] == 1 ||
backward_visited[newX][newY]) continue;
//if (forward_visited[newX][newY]) return steps;
//return forward_steps + backward_steps + 1;
backward_queue.push(newNode);
backward_visited[newX][newY] = true;
}
}
steps++;
}
return -1;
}
};