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

关于c++的FLOYD算法 P2910 [USACO08OPEN] Clear And Present Danger S 题解

算法原理
Floyd算法用于求解图中所有顶点对之间的最短路径,基于动态规划思想,通过逐步优化中间节点实现。其核心递推公式为:  
d_{ij}^{(k)} = \min(d_{ij}^{(k-1)}, d_{ik}^{(k-1)} + d_{kj}^{(k-1)})
其中 $d_{ij}^{(k)}$ 表示从i到j且仅经过前k个节点的最短路径。

例题:P2910 [USACO08OPEN] Clear And Present Danger S

题目描述

农夫约翰正驾驶一条小艇在牛勒比海上航行.

海上有 N(1≤N≤100) 个岛屿,用 1 到 N 编号.约翰从 1 号小岛出发,最后到达 N 号小岛.

一张藏宝图上说,如果他的路程上经过的小岛依次出现了 A1​,A2​,…,AM​(2≤M≤10000) 这样的序列(不一定相邻),那他最终就能找到古老的宝藏. 但是,由于牛勒比海有海盗出没.约翰知道任意两个岛屿之间的航线上海盗出没的概率,他用一个危险指数 Di,j​(0≤Di,j​≤100000) 来描述.他希望他的寻宝活动经过的航线危险指数之和最小.那么,在找到宝藏的前提下,这个最小的危险指数是多少呢?

输入格式

第一行:两个用空格隔开的正整数 N 和 M。

第二到第 M+1 行:第 i+1 行用一个整数 Ai​ 表示 FJ 必须经过的第 i 个岛屿

第 M+2 到第 N+M+1 行:第 i+M+1 行包含 N 个用空格隔开的非负整数分别表示 i 号小岛到第 1…N 号小岛的航线各自的危险指数。保证第 i 个数是 0。

输出格式

第一行:FJ 在找到宝藏的前提下经过的航线的危险指数之和的最小值。

说明 这组数据中有三个岛屿,藏宝图要求 FJ 按顺序经过四个岛屿:1 号岛屿、2 号岛屿、回到 1 号岛屿、最后到 3 号岛屿。每条航线的危险指数也给出了:航路(1,2),(2,3),(3,1) 和它们的反向路径的危险指数分别是 5,2,1。

FJ 可以通过依次经过 1,3,2,3,1,3 号岛屿以 7 的最小总危险指数获得宝藏。这条道路满足了奶牛地图的要求 (1,2,1,3)。我们避开了 1 号和 2 号岛屿之间的航线,因为它的危险指数太大了。

注意:测试数据中 a 到 b 的危险指数不一定等于 b 到 a 的危险指数!

输入输出样例

输入 

3 4 
1 
2 
1 
3 
0 5 1 
5 0 2 
1 2 0 

输出 

7 

代码:

#include <bits/stdc++.h>
#define int long long
using namespace std;
 
const int MAXN = 105;
int n, m, ans;
int dist[MAXN][MAXN];
int order[10010];
 
signed main() {
    cin >> n >> m;
    for(int i = 1; i <= m; i++) cin >> order[i];
    for(int i = 1; i <= n; i++)
        for(int j = 1; j <= n; j++) 
            cin >> dist[i][j];
    for(int k = 1; k <= n; k++)
        for(int i = 1; i <= n; i++)
            for(int j = 1; j <= n; j++)
                dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j]);
    for(int i = 2; i <= m; i++) ans += dist[order[i - 1]][order[i]];
    ans += dist[1][order[1]];
    ans += dist[order[m]][n];
    cout << ans;
    return 0;
}

以下是代码的详细分步解析:

  1. 定义
    ​​​​​​​const int MAXN = 105; 
    int n, m, ans; int dist[MAXN][MAXN]; // 存储最短路径的邻接矩阵 
    int order[10010]; // 存储订单访问顺序
    • MAXN=10^5 表示图中最多有10^5个节点
    • order数组规模10010说明最多支持10000个订单(从i=1i=m
  2. 主函数

    步骤1:初始化邻接矩阵

    for(int i = 1; i <= n; i++)
        for(int j = 1; j <= n; j++) 
            cin >> dist[i][j];
    • 输入n×n的邻接矩阵,dist[i][j]表示节点i到j的直接距离

    步骤2:Floyd-Warshall算法

    for(int k = 1; k <= n; k++)
        for(int i = 1; i <= n; i++)
            for(int j = 1; j <= n; j++)
                dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j]);
    • 通过动态规划计算所有节点对的最短路径
    • 时间复杂度O(n^3),有n≤100的规模,可行

    步骤3:路径计算

    // 累加订单节点间的路径
    for(int i = 2; i <= m; i++) 
        ans += dist[order[i - 1]][order[i]];
    
    // 添加起点和终点
    ans += dist[1][order[1]];    // 从节点1到第一个订单节点
    ans += dist[order[m]][n];    // 从最后一个订单节点到节点n
    • 总路径构成:1→order[1]→⋯→order[m]→n

算法复杂度分析算法复杂度分析​:

  • 时间复杂度:由Floyd-Warshall算法主导,为O(n^3+m)
  • 空间复杂度O(n^2)(邻接矩阵存储)

示例:
输入

3 2
2 3
0 2 3
2 0 1
3 1 0

  • Floyd计算后得到全源最短路径矩阵
  • 路径计算:dist[1→2]+dist[2→3]+dist[3→3]=2+1+0=3
    (注意:实际场景中dist[3→3]应为0)
http://www.dtcms.com/a/99797.html

相关文章:

  • Spring Boot 整合 RabbitMQ:注解声明队列与交换机详解
  • 高级SQL技巧
  • Linux(8.6)rsync
  • 33. Java 流程控制语句 If-Then-Else 语句
  • [原创](现代C++ Builder 12指南): 如何使用System.JSON?
  • Gitee批量删除仓库
  • 美食菜谱数据集 | 智能体知识库 | AI大模型
  • 力扣HOT100之普通数组:41. 缺失的第一个正数
  • Cannot find a valid baseurl for repo: centos-sclo-sclo/x86_64
  • Vue实现的表格多选方案支持跨页选择和回显功能
  • DNS网络攻击:原理剖析、危害解读与全面防御指南
  • 【Python LeetCode 专题】每日一题
  • 【20期获取股票数据API接口】如何用Python、Java等五种主流语言实例演示获取股票行情api接口之沪深A股实时最新分时MACD数据及接口API说明文档
  • 本地缓存之Guava Cache
  • Linux CentOS 7 搭建我的世界服务器详细教程 (丐版 使用虚拟机搭建)
  • CTFshow命令执行(55-71)
  • 24_原型和原型链_this
  • GitHub上免费学习工具的精选汇总
  • 数字电路基础
  • 【Java/数据结构】优先级队列(PriorityQueue)(图文版)
  • PDF处理控件Aspose.PDF教程:通过C#、Java 和 Python删除 PDF中的水印
  • 测试cursor-AI编辑器
  • Python FastApi(8):模式的额外信息、额外数据类型
  • java网盘项目,文件和文件夹用两个表还是一个表,两个表理论查询效率慢了为啥要用,有啥优势
  • 数据结构 KMP 字符串匹配算法
  • 《Python Web部署应知应会》No2:如何基于FastAPI 和 OLLAMA 架构实现高并发 AI 推理服务
  • leetcode刷题日记——跳跃游戏 II
  • 编程语言
  • 【每日论文】DINeMo: Learning Neural Mesh Models with no 3D Annotations
  • Visual Studio中创建和配置设置文件(Settings.settings) - 详细步骤指南——待调试