首页 > 编程语言 >BFS 算法专题(三):BFS 解决边权为 1 的最短路问题

BFS 算法专题(三):BFS 解决边权为 1 的最短路问题

时间:2024-11-17 13:14:57浏览次数:3  
标签:get int 边权 ret check BFS new 短路 size

目录

1. 迷宫中离入口最近的出口 

1.1 算法原理

1.2 算法代码

2. 最小基因变化 ★★★

2.1 算法原理

2.2 算法代码

3. 单词接龙

3.1 算法原理

3.2 算法代码

4. 为高尔夫比赛砍树 (hard)

4.1 算法原理

 4.2 算法代码


1. 迷宫中离入口最近的出口 

. - 力扣(LeetCode)

1.1 算法原理

核心问题: 图论 => 边权为1/边权相同 的最短路径问题

解法: 从起点开始, 进行 BFS 扩展, 第一次到达终点时, 扩展的层数, 就是最短的路径.

如何记录 BFS 扩展的层数呢??
--- 借助每一层中节点的数量(queue.size()), 使用变量 ret 记录扩展的层数.

1.2 算法代码

class Solution {
    public int nearestExit(char[][] maze, int[] entrance) {
        int[] dx = { 1, -1, 0, 0 };
        int[] dy = { 0, 0, 1, -1 };
        // 记录到达终点时, BFS 的层数
        int ret = 0;
        int m = maze.length, n = maze[0].length;
        boolean[][] check = new boolean[m][n];
        Queue<int[]> q = new LinkedList<>();
        q.offer(entrance);
        check[entrance[0]][entrance[1]] = true;
        while (!q.isEmpty()) {
            int size = q.size();
            ret++;
            while (size-- != 0) {
                int[] tmp = q.poll();
                int a = tmp[0], b = tmp[1];
                for (int k = 0; k < 4; k++) {
                    int x = a + dx[k], y = b + dy[k];
                    if (x >= 0 && x < m && y >= 0 && y < n && !check[x][y] && maze[x][y] == '.') {
                        if (x == 0 || x == m - 1 || y == 0 || y == n - 1) return ret;
                        q.offer(new int[] { x, y });
                        check[x][y] = true;
                    }
                }
            }
        }
        return -1;
    }
}

2. 最小基因变化 ★★★

. - 力扣(LeetCode)

2.1 算法原理

问题转化: 转化为 => 图论 边权为1的最短路问题

  1. 每变一个字符(基因的变化)看做一步, BFS 选出达到目标基因序列时的最短路.
  2. 注意: 不能重复搜索已经搜索过的状态
  3. 注意: 经过变化的字符串, 应该在 bank 基因库中存在
  4. 使用 哈希表 标记已经搜索过的状态
  5. 使用 哈希表 保存基因库中的字符(便于查找变化的字符串是否在基因库中)

2.2 算法代码

class Solution {
    public int minMutation(String startGene, String endGene, String[] bank) {
        Queue<String> q = new LinkedList<>();
        // 判断是否重复转化
        Set<String> check = new HashSet<>();
        // 判断基因库中是否存在
        Set<String> hash = new HashSet<>();
        for(String s : bank) hash.add(s);
        
        if(!hash.contains(endGene)) return -1;
        if(startGene.equals(endGene)) return 0;

        char[] change = {'A', 'C', 'G', 'T'};

        int ret = 0;
        q.offer(startGene);
        check.add(startGene);
        while(!q.isEmpty()) {
            int size = q.size();
            ret++;
            while(size-- != 0) {
                String s = q.poll();
                for(int i = 0; i < 8; i++) {
                    char[] tmp = s.toCharArray();
                    for(int j = 0; j < 4; j++) {
                        tmp[i] = change[j];
                        String next = new String(tmp);
                        if(hash.contains(next) && !check.contains(next)) {
                            if(next.equals(endGene)) return ret;
                            check.add(next);
                            q.offer(next);
                        }
                    }
                }
            }
        }
        return -1;
    }
}

3. 单词接龙

. - 力扣(LeetCode)

3.1 算法原理

  • 本题解法与上题解法完全一致.

  • 只不过返回值略有差异. 本题返回达到目标字符串时, 所涉及到的最少的字符串的个数(最短路 +1)

3.2 算法代码

class Solution {
    public int ladderLength(String beginWord, String endWord, List<String> wordList) {
        // 把字典中的字符串, 放到哈希表中 => 查找效率 O(1)
        Set<String> hash = new HashSet<>(wordList);
        if(!hash.contains(endWord)) return 0;
        int n = beginWord.length();
        // 判断是否重复转化
        Set<String> check = new HashSet<>();
        Queue<String> q = new LinkedList<>();
        int step = 0;
        q.offer(beginWord);
        check.add(beginWord);
        while(!q.isEmpty()) {
            int size = q.size();
            step++;
            while(size-- != 0) {
                String s = q.poll();
                for(int i = 0; i < n; i++) {
                    char[] tmp = s.toCharArray();
                    for(char ch = 'a'; ch <= 'z'; ch++) {
                        tmp[i] = ch;
                        String next = new String(tmp);
                        if(hash.contains(next) && !check.contains(next)) {
                            if(next.equals(endWord)) return step + 1;
                            q.offer(next);
                            check.add(next);
                        }
                    }
                }
            }
        }
        return 0;
    }
}

4. 为高尔夫比赛砍树 (hard)

. - 力扣(LeetCode)

4.1 算法原理

  • 对砍树的顺序做好记录(所砍树的高度应从小到大), 并记录好每一颗树的位置.

  • 从起点开始, 对这些位置依次进行 BFS, 找出到达这些位置的最短路.

  • 返回到达所有位置所需最少步数之和

 4.2 算法代码

class Solution {
    int m, n;
    int[] dx = new int[] { 1, -1, 0, 0 };
    int[] dy = new int[] { 0, 0, 1, -1 };

    public int cutOffTree(List<List<Integer>> forest) {
        m = forest.size(); n = forest.get(0).size();
        List<int[]> trees = new ArrayList<>();
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                if (forest.get(i).get(j) > 1) trees.add(new int[] {i, j});
            }
        }
        // 依次需要砍的树(树的高度从小到大)
        Collections.sort(trees, (a, b) -> forest.get(a[0]).get(a[1]) - forest.get(b[0]).get(b[1]));
        int step = 0;
        int curX = 0, curY = 0;
        for (int[] t : trees) {
            int x = t[0], y = t[1];
            int ret = bfs(x, y, curX, curY, forest);
            if (ret == -1) return -1;
            step += ret;
            curX = x;
            curY = y;
        }
        return step;
    }

    public int bfs(int x, int y, int curX, int curY, List<List<Integer>> forest) {
        int ret = 0;
        if (curX == x && curY == y) return 0;
        boolean[][] check = new boolean[m][n];
        Queue<int[]> q = new LinkedList<>();
        q.offer(new int[] { curX, curY });
        check[curX][curY] = true;
        while (!q.isEmpty()) {
            int size = q.size();
            ret++;
            while (size-- != 0) {
                int[] t = q.poll();
                int a = t[0], b = t[1];
                for (int k = 0; k < 4; k++) {
                    int i = a + dx[k], j = b + dy[k];
                    if (i >= 0 && i < m && j >= 0 && j < n && forest.get(i).get(j) != 0 && !check[i][j]) {
                        if (forest.get(i).get(j) == forest.get(x).get(y))
                            return ret;
                        q.offer(new int[] { i, j });
                        check[i][j] = true;
                    }
                }
            }
        }
        return -1;
    }
}

END

标签:get,int,边权,ret,check,BFS,new,短路,size
From: https://blog.csdn.net/2401_83595513/article/details/143601408

相关文章

  • 【Debug】“逻辑与&“与“短路与&&“、“逻辑或|“与“短路或||“
    前情提要:今天用C++写数据结构代码,写一个while循环,p是一个链表指针,有两个条件,用&&连接,如下:while(p->data!=data&&p!=NULL)然后发现第二个条件p!=NULL被标黄,显示Conditionisalwaystruewhenreached,查了一下才发现&&是短路与。知识搜罗:&:逻辑与;|:逻辑或&&:短......
  • DAY65||Bellman_ford 队列优化算法(又名SPFA)|bellman_ford之判断负权回路|bellman_ford
    Bellman_ford队列优化算法(又名SPFA)94.城市间货物运输I思路大家可以发现Bellman_ford算法每次松弛都是对所有边进行松弛。但真正有效的松弛,是基于已经计算过的节点在做的松弛。给大家举一个例子:本图中,对所有边进行松弛,真正有效的松弛,只有松弛边(节点1->节点2)和......
  • 1018 Public Bike Management(多条最短路径,dijkstra+dfs+回溯)
     该题考查多条最短路径的计算,对比单条最短路,主要有两点不同:1.在dijkstra算法中记录每个结点的所有相同最短距离的前结点2.在dfs找多条最短路径时需要回溯状态拿到所有最短路径以后,我们根据题意去获取相应的结果即可1#include<bits/stdc++.h>2usingnamespacestd;......
  • 铅酸电池或锂电池的电动自行车, 怎么防止过充或短路?
    防止电动自行车的铅酸电池或锂电池过充和短路是确保安全使用的重要措施。以下是一些建议和方法:防止过充使用合适的充电器:确保使用与电池类型和规格相匹配的充电器。原装或经过认证的充电器通常具有适当的电压和电流输出。智能充电器:选择具有充电截......
  • BFS 算法专题(二):BFS 解决 FloodFill 算法
    目录1.图像渲染1.1算法原理1.2算法代码2.岛屿数量2.1算法原理2.2算法代码3.岛屿的最大面积3.1算法原理3.2算法代码4.被围绕的区域4.1算法原理4.2算法代码1.图像渲染.-力扣(LeetCode)1.1算法原理在本专题之前,对于FloodFill算法,我们就已......
  • 迪杰斯特拉算法、弗洛伊德算法和BFS(广度优先搜索)
    迪杰斯特拉算法、弗洛伊德算法和BFS(广度优先搜索)都是用于求解最短路径问题的经典算法,它们各自有不同的特点和适用场景。以下是对这三种算法的介绍、区别以及代码实现的简要概述。迪杰斯特拉算法(Dijkstra'salgorithm)介绍:迪杰斯特拉算法是一种单源最短路径算法,用于计算一个......
  • 每日OJ题_牛客_kotori和迷宫_BFS_C++_Java
    目录牛客_kotori和迷宫_BFS题目解析C++代码Java代码牛客_kotori和迷宫_BFSkotori和迷宫描述:        kotori在一个n*m迷宫里,迷宫的最外层被岩浆淹没,无法涉足,迷宫内有k个出口。kotori只能上下左右四个方向移动。她想知道有多少出口是她能到达的,最近的出口离她......
  • 最短路径算法综述:原理、比较与实现
    最短路径算法综述:原理、比较与实现一、引言在图论和计算机科学领域,最短路径问题是一个经典且重要的研究内容。它在交通导航、网络路由、物流规划等众多实际应用场景中有着广泛的应用。本文将详细介绍几种常见的最短路径算法,包括Dijkstra算法、Bellman-Ford算法、Floy......
  • P8906 [USACO22DEC] Breakdown P [最短路]
    P8906[USACO22DEC]BreakdownPSolution经典trick,删边比较难处理,转换成加边,倒着处理。那我们接下来要考虑,怎么记录状态,以及,每加一次边要如何更新状态。还是比较套路地,我们可以求出\(1\)到某个点\(i\)经过\(k/2\)条边的最短路,再求出\(i\)到\(n\)经过\(k-k/2......
  • 计蒜客:网络延迟(DFS/BFS)
     题目要求的是最远的两个节点的距离,即求树的直径(树中所有最短路径距离的最大值即为树的直径 求树的直径有两种做法,两次bfs(或者dfs),另一种是用树形DP本文用两次DFS实现#include<bits/stdc++.h>usingnamespacestd;intn,u,v;vector<int>graph[50005];vector<bool>vi......