当前位置:首页 > 洛谷题解 > 洛谷P4554题终极指南:双端队列BFS解决网格图最短路径问题 | 算法新手必备

洛谷P4554题终极指南:双端队列BFS解决网格图最短路径问题 | 算法新手必备

5天前洛谷题解54

截图未命名.jpg 洛谷P4554题终极指南:双端队列BFS解决网格图最短路径问题 | 算法新手必备 双端队列BFS 网格图最短路径 算法优化 洛谷P4554 图论算法 第1张

一、问题理解与算法思路

题目要求在给定的网格中,从起点到终点找到一条路径,使得经过不同字符的边数最少。这道题考察了两个核心算法点:广度优先搜索(BFS)和双端队列优化。我们采用双端队列优化的BFS算法,既保证了正确性又提高了效率。

解题关键步骤

  1. 初始化距离数组为无穷大

  2. 使用双端队列存储待处理节点

  3. 根据移动成本决定入队位置

  4. 及时更新最短距离

二、完整代码实现(带详细注释)

#include <iostream>
#include <deque>
#include <cstring>
using namespACe std;

const int N = 510;
char grid[N][N];  // 存储网格图
int dist[N][N];   // 存储到每个点的最短距离
int dx[] = {-1, 1, 0, 0};  // 四个方向的x偏移量
int dy[] = {0, 0, -1, 1};  // 四个方向的y偏移量
int n, m, x1, y1, x2, y2;  // 网格大小和起点终点坐标

int bfs() {
    memset(dist, 0x3f, sizeof dist);  // 初始化距离为极大值
    deque<pair<int, int>> q;  // 双端队列
    q.push_back({x1, y1});
    dist[x1][y1] = 0;  // 起点距离为0
    
    while (!q.empty()) {
        auto t = q.front();
        q.pop_front();
        
        // 遍历四个方向
        for (int i = 0; i < 4; i++) {
            int nx = t.first + dx[i], ny = t.second + dy[i];
            if (nx < 1 || nx > n || ny < 1 || ny > m) continue;  // 越界检查
            
            // 计算移动成本:如果字符不同则成本为1,否则为0
            int cost = (grid[nx][ny] != grid[t.first][t.second]);
            if (dist[nx][ny] > dist[t.first][t.second] + cost) {
                dist[nx][ny] = dist[t.first][t.second] + cost;
                // 根据成本决定插入队列的位置
                if (cost == 0) q.push_front({nx, ny});  // 成本0插入队首
                else q.push_back({nx, ny});  // 成本1插入队尾
            }
        }
    }
    return dist[x2][y2];  // 返回终点的最短距离
}

int main() {
    while (cin >> n >> m, n || m) {  // 处理多组输入直到n和m都为0
        // 读取网格图
        for (int i = 1; i <= n; i++)
            for (int j = 1; j <= m; j++)
                cin >> grid[i][j];
        cin >> x1 >> y1 >> x2 >> y2;
        x1++, y1++, x2++, y2++; // 转换为1-based索引
        cout << bfs() << endl;
    }
    return 0;
}

三、算法核心解析

  1. 双端队列优化:根据移动成本决定节点插入位置,0成本插入队首,1成本插入队尾

  2. 距离松弛:只有当找到更短路径时才更新距离并重新入队

  3. 边界处理:正确处理网格边界防止越界访问

  4. 多组输入:使用while循环处理多组测试数据

四、复杂度分析与优化

  1. 时间复杂度:O(nm),每个节点最多被处理一次

  2. 空间复杂度:O(nm),存储距离矩阵和队列

  3. 优化建议

五、常见问题解答

Q:为什么使用双端队列而不是普通队列? A:双端队列可以保证0成本的移动优先处理,类似于优先级队列但常数更小。

Q:如何处理更大的网格? A:可以考虑使用更高效的数据结构如跳表,或者优化内存访问模式。

Q:算法是否可以扩展到三维网格? A:可以,只需增加z方向的移动和相应处理逻辑。


原创内容 转载请注明出处

分享给朋友:

发表评论

访客

看不清,换一张

◎欢迎参与讨论,请在这里发表您的看法和观点。