双端队列广搜

该博客主要讨论了一种寻找网格中从(0,0)到(n,m)最短路径的算法。通过将网格点视为节点,斜杠视为可连接路径,使用双端队列进行广度优先搜索,优化路径长度为0或1的情况,从而高效求解最短路径。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

175. 电路维修

题目链接
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> PII;
const int N = 510;

int n, m;
char g[N][N];
int d[N][N];

int bfs() {
    memset(d, 0x3f, sizeof(d));

    deque<PII> dq;
    dq.push_back({0, 0});
    d[0][0] = 0;

    int dx[4] = {-1, -1, 1, 1}, dy[4] = {-1, 1, 1, -1};
    int ix[4] = {-1, -1, 0, 0}, iy[4] = {-1, 0, 0, -1};
    char cs[] = "\\/\\/";

    while (dq.size()) {
        auto t = dq.front();
        dq.pop_front();

        int x = t.first, y = t.second;
        for (int i = 0; i < 4; ++i) {
            int a = x + dx[i], b = y + dy[i];
            if (a >= 0 && a <= n && b >= 0 && b <= m) {
                int w = 0;
                int j = x + ix[i], k = y + iy[i];
                if (g[j][k] != cs[i])
                    w = 1;

                if (d[a][b] > d[x][y] + w) {
                    d[a][b] = d[x][y] + w;
                    if (w)
                        dq.push_back({a, b});
                    else
                        dq.push_front({a, b});
                }
            }
        }
    }
    if (d[n][m] == 0x3f3f3f3f)
        return -1;
    else
        return d[n][m];
}

int main() {
    int T;
    scanf("%d", &T);
    while (T--) {
        scanf("%d%d", &n, &m);
        for (int i = 0; i < n; ++i)
            scanf("%s", g[i]);
        int t = bfs();
        if (t == -1)
            puts("NO SOLUTION");
        else
            printf("%d\n", t);
    }
    return 0;
}

题解:这个题目就是把网格点看成是一个个结点,斜杠看成是可连接的路径,求从(0,0)出发到达(n,m)点的最短路径,这里要巧妙地开两个数组分别储存结点位置和路径位置,之后开一个双端队列deque,因为这里的路径长度只看做0或者1,所以用双端队列比优先队列要快,如果当前选的路径长度为0,就加到队首,如果长度是1,就加到队尾,这样保证最优。

### 使用Python实现广度优先索(BFS)算法进行地图构建 为了利用广度优先索(BFS)创建地图,可以考虑将地图表示为图结构中的节点和边。每个位置视为一个节点,相邻的位置通过边连接起来。下面展示了一个简单的基于网格的地图模型,在此之上实现了BFS。 #### 地图初始化 首先定义地图类`MapGrid`用于存储地图数据以及执行基本操作: ```python class MapGrid: def __init__(self, width, height): self.width = width self.height = height self.walls = [] # List of wall coordinates def in_bounds(self, id): (x, y) = id return 0 <= x < self.width and 0 <= y < self.height def passable(self, id): return id not in self.walls def neighbors(self, id): (x, y) = id results = [(x+1, y), (x, y-1), (x-1, y), (x, y+1)] results = filter(self.in_bounds, results) results = filter(self.passable, results) return results ``` 这段代码描述了如何设置一个二维数组形式的地图,并提供了判断坐标是否有效、可通行的方法,还有获取邻居坐标的函数[^1]。 #### 广度优先索实现 接下来编写实际的BFS逻辑,它接受起始点作为输入参数并返回访问过的路径列表: ```python from collections import deque def bfs(map_grid, start): frontier = deque([start]) came_from = {} came_from[start] = None while frontier: current = frontier.popleft() for next in map_grid.neighbors(current): if next not in came_from: frontier.append(next) came_from[next] = current return came_from ``` 这里采用双端队列`deque()`来高效处理待探索集合;字典`came_from`记录下每一个被发现的新地点是从哪里到达的,以便之后重建完整的遍历路线。 #### 构建地图可视化 最后一步是绘制出最终形成的地图图像,这可以通过matplotlib库完成: ```python import matplotlib.pyplot as plt def draw_map(came_from, map_grid): fig, ax = plt.subplots(figsize=(8, 8)) for pos in came_from.keys(): if pos != start_pos: prev_pos = came_from[pos] line = plt.Line2D((pos[0], prev_pos[0]), (pos[1], prev_pos[1]), lw=1., color='blue') ax.add_line(line) for w in map_grid.walls: rect = plt.Rectangle(w[::-1], 1, 1, facecolor="black", edgecolor="none") ax.add_patch(rect) ax.set_xlim(-0.5,map_grid.width-.5) ax.set_ylim(-0.5,map_grid.height-.5) plt.gca().invert_yaxis() plt.show() if __name__ == "__main__": grid_width = 10 grid_height = 7 walls = ((1, 3),(4, 2)) # Example obstacles/wall positions. start_pos = (0, 0) my_map = MapGrid(grid_width, grid_height) my_map.walls.extend(walls) path_info = bfs(my_map, start=start_pos) draw_map(path_info, my_map) ``` 上述脚本会生成一张图形化界面显示由起点出发所能触及到的所有区域,其中黑色方块代表障碍物,蓝色线条则指示出了具体的行走轨迹。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值