算法学习:启发式搜索

理论

概念

启发式搜索(Heuristically Search)又称为有信息搜索(Informed Search),它是利用问题拥有的启发信息来引导搜索,达到减少搜索范围、降低问题复杂度的目的,这种利用启发信息的搜索过程称为启发式搜索。

估价函数

启发式函数: h(n),它用来评价哪些结点最有希望的是一个我们要找的结点,h(n) 会返回一个非负实数,也可以认为是从结点n的目标结点路径的估计成本。
注意:估价函数的选取十分重要,会直接影响到算法的效率。

代码模板

有点类似于bfs,但这里使用的是优先队列,估价函数即优先级。

def AstarSearch(graph, start, end): 
    pq = collections.priority_queue() # 优先级 —> 估价函数
    pq.append([start]) 
    visited.add(start) 
    while pq: 
        node = pq.pop() # can we add more intelligence here ? 
        visited.add(node) 
        process(node) 
        nodes = generate_related_nodes(node) 
        unvisited = [node for node in nodes if node not in visited] 
        pq.push(unvisited)

算法实践

1091. 二进制矩阵中的最短路径

问题描述

给你一个 n x n 的二进制矩阵 grid 中,返回矩阵中最短 畅通路径 的长度。如果不存在这样的路径,返回 -1

二进制矩阵中的 畅通路径 是一条从 左上角 单元格(即,(0, 0))到 右下角 单元格(即,(n - 1, n - 1))的路径,该路径同时满足下述要求:

  • 路径途经的所有单元格的值都是 0
  • 路径中所有相邻的单元格应当在 8 个方向之一 上连通(即,相邻两单元之间彼此不同且共享一条边或者一个角)。
    畅通路径的长度 是该路径途经的单元格总数。
示例
解题思路

先准备好8个方向的变化变量,然后从(0,0)开始进行类bfs搜索,使用优先队列,估价函数为:到当前位置花费的成本 + x/y坐标和上一个位置差的绝对值的最大值。

代码示例
class Solution {
    int len = 0;
    int[][] directions = new int[][]{{-1, -1}, {0, -1}, {1, -1}, {1, 0}, {1, 1}, {0, 1}, {-1, 1}, {-1, 0}};

    public int shortestPathBinaryMatrix(int[][] grid) {
        len = grid.length;
        if (grid[0][0] == 1 || grid[len - 1][len - 1] == 1) {
            return -1;
        }
        if (len == 1) {
            return 1;
        }

        Queue<Node> queue = new PriorityQueue<>(10, Comparator.comparingInt(Node::cost));
        queue.offer(new Node(0, 0, 1));
        grid[0][0] = 1;
        while (!queue.isEmpty()) {
            Node current = queue.poll();
            for (int i = 0; i < directions.length; i++) {
                int x = current.x + directions[i][0];
                int y = current.y + directions[i][1];
                if (x == len - 1 && y == len - 1) {
                    return current.step + 1;
                }
                if (x < 0 || x >= len || y < 0 || y >= len) {
                    continue;
                }
                if (grid[x][y] == 0 || grid[x][y] > grid[current.x][current.y] + 1) {
                    grid[x][y] = current.step + 1;
                    Node newNode = new Node(x, y, grid[x][y]);
                    queue.add(newNode);
                }
            }
        }
        return -1;
    }

    class Node {
        public int x;
        public int y;
        public int step;

        public Node() {
        }

        public Node(int x, int y, int step) {
            this.x = x;
            this.y = y;
            this.step = step;
        }

        public int cost() {
            return step + Math.max(Math.abs(len - x - 1), Math.abs(len - y - 1));
        }
    }
}
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

友情链接更多精彩内容