LintCode-611: Knight Shortest Path (BFS经典题)

思路就是用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; 
    }
};
 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值