当前位置: 首页 > article >正文

卡码网KamaCoder 97. 小明逛公园

题目来源:97. 小明逛公园

C++题解(来源代码随想录):Floyd 算法

动规五部曲:

  • 确定dp数组(dp table)以及下标的含义

grid[i][j][k] = m,表示 节点i 到 节点j 以[1...k] 集合为中间节点的最短距离为m。节点i 到 节点j 中间一定经过很多节点,那么你能用什么方式来表述中间这么多节点呢?所以 这里的k不能单独指某个节点,k 一定要表示一个集合,即[1...k] ,表示节点1 到 节点k 一共k个节点的集合。

  • 确定递推公式

我们分两种情况:

  1. 节点i 到 节点j 的最短路径经过节点k
  2. 节点i 到 节点j 的最短路径不经过节点k

对于第一种情况,grid[i][j][k] = grid[i][k][k - 1] + grid[k][j][k - 1]

节点i 到 节点k 的最短距离 是不经过节点k,中间节点集合为[1...k-1],所以 表示为grid[i][k][k - 1];节点k 到 节点j 的最短距离 也是不经过节点k,中间节点集合为[1...k-1],所以表示为 grid[k][j][k - 1]

第二种情况,grid[i][j][k] = grid[i][j][k - 1]

因为我们是求最短路,即: grid[i][j][k] = min(grid[i][k][k - 1] + grid[k][j][k - 1], grid[i][j][k - 1])

  • dp数组如何初始化

grid[i][j][k] = m,表示 节点i 到 节点j 以[1...k] 集合为中间节点的最短距离为m。刚开始初始化k 是不确定的。把k 填成1,那如何上来就知道 节点2 经过节点1 到达节点6的最短距离是多少 呢。所以 只能 把k 赋值为 0,本题 节点0 是无意义的,节点是从1 到 n。

这样我们在下一轮计算的时候,就可以根据 grid[i][j][0] 来计算 grid[i][j][1],此时的 grid[i][j][1] 就是 节点i 经过节点1 到达 节点j 的最小距离了。

  • 确定遍历顺序

从递推公式:grid[i][j][k] = min(grid[i][k][k - 1] + grid[k][j][k - 1], grid[i][j][k - 1]) 可以看出,我们需要三个for循环,分别遍历i,j 和k

而 k 依赖于 k - 1, i 和j 的到 并不依赖与 i - 1 或者 j - 1 等等。

我们把 k =0 的 i 和j 对应的数值都初始化了,这样才能去计算 k = 1 的时候 i 和 j 对应的数值。所以遍历k 的for循环一定是在最外面,这样才能一层一层去遍历。

  • 举例推导dp数组
#include <iostream>
#include <vector>
using namespace std;

int main() {
    int n, m, p1, p2, val;
    cin >> n >> m;

    vector<vector<int>> grid(n + 1, vector<int>(n + 1, 10005));  // 因为边的最大距离是10^4

    for(int i = 0; i < m; i++){
        cin >> p1 >> p2 >> val;
        grid[p1][p2] = val;
        grid[p2][p1] = val; // 注意这里是双向图

    }
    // 开始 floyd
    for (int k = 1; k <= n; k++) {
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= n; j++) {
                grid[i][j] = min(grid[i][j], grid[i][k] + grid[k][j]);
            }
        }
    }
    // 输出结果
    int z, start, end;
    cin >> z;
    while (z--) {
        cin >> start >> end;
        if (grid[start][end] == 10005) cout << -1 << endl;
        else cout << grid[start][end] << endl;
    }
}

使用二维数组grid[i][j] = min(grid[i][j], grid[i][k] + grid[k][j]); 可以看成贪心算法,节点 i 到节点 j 是否经过节点 k ,进而更新grid[i][j]


http://www.kler.cn/a/369830.html

相关文章:

  • IP协议特性
  • AWScurl笔记
  • SpringBoot统一功能处理
  • 【Linux】Linux编译器-g++、gcc、动静态库
  • 【数据分享】1929-2024年全球站点的逐月平均能见度(Shp\Excel\免费获取)
  • wxwidgets直接获取系统图标,效果类似QFileIconProvider
  • html之文字,图片,链接,音视频
  • C语言 | Leetcode C语言题解之第517题超级洗衣机
  • AIGC学习笔记(2)——AI大模型开发工程师
  • React 组件 API
  • Python测试框架—pytest详解
  • TensorFlow面试整理-给定一个任务(如图像分类、文本分类),如何从头构建一个TensorFlow模型?
  • 工厂方法模式 — 设计模式
  • 【云计算】KVM虚拟化部署
  • Redis和MySQL如何保证数据一致性
  • SQLAlchemy 连接 dm
  • 基于Multisim的单双声道音频功率放大电路设计与仿真
  • 哈希及其封装实现unordermap和set
  • PSI-BLAST位点特异性矩阵PSSM和ProteinMPNN中氨基酸顺序映射
  • 华为OD机试真题---字符串摘要
  • 【含开题报告+文档+PPT+源码】基于SSM的旅游与自然保护平台开发与实现
  • 重工业数字化转型创新实践:某国家特大型钢铁企业如何快速落地基于实时数仓的数据分析平台
  • 开源模型应用落地-qwen模型小试-Qwen2.5-7B-Instruct-玩转ollama(一)
  • 【最新华为OD机试E卷-支持在线评测】机器人活动区域(200分)多语言题解-(Python/C/JavaScript/Java/Cpp)
  • 如何通过自动化有效地简化 Active Directory 操作?
  • Java基于微信小程序的童装商城的设计与实现,附源码+文档