专栏文章

题解:P1713 麦当劳叔叔的难题

P1713题解参与者 1已保存评论 0

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
0 条
当前快照
1 份
快照标识符
@mipcbl7l
此快照首次捕获于
2025/12/03 09:40
3 个月前
此快照最后确认于
2025/12/03 09:40
3 个月前
查看原文

问题分析

这是一个关于在网格中寻找路径的问题,需要找到从左下角到右上角的最短路径和最长路径(每个格子只能经过一次),然后计算它们的时间差。

解决思路

最短路径:可以使用广度优先搜索(BFS)来找到,因为 BFS 保证找到的路径是最短的。 最长路径:这是一个 NP-Hard 问题,在本题中,我们可以通过分析发现,最长路径的长度等于网格总格子数减去障碍物数量再减 1。

C++ 代码实现

CPP
#include <iostream>
#include <vector>
#include <queue>
#include <utility>
#include <set>
using namespace std;

int main() {
    int n, m;
    cin >> n >> m;
    
    // 障碍物的集合,用于快速判断某个格子是否是障碍物
    set<pair<int, int>> obstacles;
    for (int i = 0; i < m; ++i) {
        int x, y;
        cin >> x >> y;
        obstacles.insert({x, y});
    }
    
    // 起点和终点
    pair<int, int> start = {1, 1};
    pair<int, int> end = {n, n};
    
    // 如果起点或终点是障碍物,直接输出0
    if (obstacles.count(start) || obstacles.count(end)) {
        cout << 0 << endl;
        return 0;
    }
    
    // BFS计算最短路径
    vector<vector<bool>> visited(n + 1, vector<bool>(n + 1, false));
    queue<pair<pair<int, int>, int>> q;
    q.push({start, 0});
    visited[1][1] = true;
    int min_time = -1;
    
    // 四个方向:上、右、下、左
    vector<pair<int, int>> directions = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}};
    
    while (!q.empty()) {
        auto [pos, time] = q.front();
        q.pop();
        int x = pos.first;
        int y = pos.second;
        
        // 如果到达终点,记录最短时间并退出循环
        if (x == n && y == n) {
            min_time = time;
            break;
        }
        
        // 尝试四个方向
        for (auto [dx, dy] : directions) {
            int nx = x + dx;
            int ny = y + dy;
            
            // 检查是否越界、是否是障碍物、是否已访问
            if (nx >= 1 && nx <= n && ny >= 1 && ny <= n && 
                !obstacles.count({nx, ny}) && !visited[nx][ny]) {
                visited[nx][ny] = true;
                q.push({{nx, ny}, time + 1});
            }
        }
    }
    
    // 计算最长路径
    int max_time = n * n - m - 1;
    
    // 输出结果
    cout << max_time - min_time << endl;
    
    return 0;
}

代码解释

输入处理:读取网格大小 n 和障碍物数量 m,然后将每个障碍物的坐标存入集合中。
起点和终点检查:如果起点或终点是障碍物,直接输出 0。
BFS 计算最短路径: 使用队列进行 BFS,每个元素包含当前位置和到达该位置的时间。
使用 visited 数组记录已经访问过的格子,避免重复访问。
四个方向分别是上、右、下、左,按顺序尝试每个方向。
当到达终点时,记录最短时间并退出循环。
计算最长路径:最长路径的长度等于总格子数减去障碍物数量再减 1。
输出结果:输出最长路径和最短路径的时间差。
时间复杂度:BFS 的时间复杂度是 O (n²),因为每个格子最多被访问一次
空间复杂度:主要是 visited 数组和队列的空间,也是 O (n²)。
这个算法高效地解决了问题,通过 BFS 找到最短路径,并通过分析得出最长路径的长度。

评论

0 条评论,欢迎与作者交流。

正在加载评论...