L2-001 紧急救援(迪杰斯特拉应用)

2024-04-23 20:58

本文主要是介绍L2-001 紧急救援(迪杰斯特拉应用),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

作为一个城市的应急救援队伍的负责人,你有一张特殊的全国地图。在地图上显示有多个分散的城市和一些连接城市的快速道路。每个城市的救援队数量和每一条连接两个城市的快速道路长度都标在地图上。当其他城市有紧急求助电话给你的时候,你的任务是带领你的救援队尽快赶往事发地,同时,一路上召集尽可能多的救援队。

输入格式:

输入第一行给出4个正整数N、M、S、D,其中N(2≤N≤500)是城市的个数,顺便假设城市的编号为0 ~ (N−1);M是快速道路的条数;S是出发地的城市编号;D是目的地的城市编号。

第二行给出N个正整数,其中第i个数是第i个城市的救援队的数目,数字间以空格分隔。随后的M行中,每行给出一条快速道路的信息,分别是:城市1、城市2、快速道路的长度,中间用空格分开,数字均为整数且不超过500。输入保证救援可行且最优解唯一。

输出格式:

第一行输出最短路径的条数和能够召集的最多的救援队数量。第二行输出从S到D的路径中经过的城市编号。数字间以空格分隔,输出结尾不能有多余空格。

输入样例:

4 5 0 3
20 30 40 10
0 1 1
1 3 2
0 3 3
0 2 2
2 3 2

输出样例:

2 60
0 1 3

这个题目很热闹啊,又是最短路,最短路经过最短条数,又是每个城市都有一个权值,从起点到终点的权值最大,还要输出路径(心想这都是啥?我只会求最短路的长度,还是自己太菜了,没有对迪杰斯特拉有很透彻的理解,还是自己太菜)。所以写个博客补充一下知识。

这个题目是从起点最快(最短路)到达终点,但是还有另一个要求,经过节点的权值和要尽量大,还要输出路径。

普通的最短路就是套模板。这个输出路径就是用一个数组来找这个点的前驱节点,然后在输出路径的时候,就像链表式的,往前找前驱节点,就是下面这样 path[ ]数组是一个点的前驱节点,然后存到vector 中,倒序输出,就得到路径。  

void print()
{int i;vector<int>mp;for(i=e;i!=s;i=path[i])mp.push_back(i);	mp.push_back(i);reverse(mp.begin(),mp.end());for(int i=0;i<mp.size();i++){if(i)cout<<' ';cout<<mp[i];}	
}

当然还有DFS回溯输出路径(我好菜,递归也没有学的很精),先递到起点,然后再往回回溯输点,这种思想要记住,对于一些输出前驱路径的要求DFS递归输出就可以了,下面代码:
 

 
//dfs回溯输出  
//X一开始传进终点 
void dfs(int x)
{if(x==s)printf("%d",x);else{dfs(path[x]);printf(" %d",x);}	
}

然后看这个最短路径经过路的条数,这个我也不是很懂(菜死了我,只会套板子),我们需要新开一个数组就是由原点到各个点的路径长度,就是过了几条边。迪杰斯特拉基本的东西就是由原点开始找到那个权值最小的那个临近点,将它放进最短路答案的集合中,再由这个点出发到其他的点,看看由原点到这个点,还是由这个新的出发点到这个点近,近的话,更新数据,近的话(以下这个操作我不是很明白,听大神说是 优化用的,不知道怎么搞的),就是近的话,由原点到这个点的路径边数变为上一个点(上一个点作为出发点找他周围的点;就是上一个点过来的到这个点了)路径边数  (举个例子0->1 长度是1,现在1->2 数据要更新,权值更新为d[pos]+map[pos][j] (注意),由原点到这个2点路径长度变为 1(注意),然后在下一次循环时候,这个条件!vis[j]&&d[j]>d[pos]+map[pos][j] 就不会满足(注意),去else if 那个条件进去,由原点到这个点的路径长度这时 1+1=2 更新了,不知道搞这样子是为啥,可能有更高级的用处,我辣鸡 不是很懂为啥这样做)。就是下面这个操作。好玄。   

for(int i=0;i<n;i++)   //这个不影响  {minv=inf;for(int j=0;j<n;j++){if(!vis[j]&&minv>d[j]){minv=d[j];pos=j;}}vis[pos]=1;for(int j=0;j<n;j++){if(!vis[j]&&d[j]>d[pos]+map[pos][j]){d[j]=map[pos][j]+d[pos];pathsum[j]=pathsum[pos];      valsum[j]=valsum[pos]+val[j];path[j]=pos;}else if(!vis[j]&&d[j]==d[pos]+map[pos][j]){pathsum[j]+=pathsum[pos];  if(valsum[j]<valsum[pos]+val[j]){valsum[j]=valsum[pos]+val[j];path[j]=pos;}}}}

 还有一个需求,(在每个点上都会有一个权值,经过时会加上),求出在最短路的基础上看看怎么使得这个权值最大。我们现在再来一个数组来存储由原点到各个点的权值,一开始初始条件就是每个城市每个点都是 原先的权值。就是上面的代码。这个还是比较好想的。

代码:

 

#include<iostream>
#include<stdio.h>
#include<string>
#include<vector>
#include<algorithm>
#include<string.h>
const int maxn=1005;
typedef long long ll;
using namespace std;
const int inf=1e8;int map[maxn][maxn];
int d[maxn];           //到每个点经过路的权值  
int vis[maxn];int val[maxn];       //每个点初始的权值 
int valsum[maxn];   //由起点到每个点的权值  
int path[maxn];			//这个点之前的点 
int pathsum[maxn];      //到每个点的经过路的条数 int n,m,s,e;void init()
{memset(vis,0,sizeof(vis));memset(path,0,sizeof(path));memset(pathsum,0,sizeof(pathsum));for(int i=0;i<n;i++){for(int j=0;j<n;j++)if(i==j)map[i][j]=0;elsemap[i][j]=inf;valsum[i]=val[i];}	
} void jd()
{for(int i=0;i<n;i++){d[i]=map[s][i];}pathsum[s]=1;d[s]=0;int minv=inf;int pos;for(int i=0;i<n;i++){minv=inf;for(int j=0;j<n;j++){if(!vis[j]&&minv>d[j]){minv=d[j];pos=j;}}vis[pos]=1;for(int j=0;j<n;j++){if(!vis[j]&&d[j]>d[pos]+map[pos][j]){d[j]=map[pos][j]+d[pos];pathsum[j]=pathsum[pos];valsum[j]=valsum[pos]+val[j];path[j]=pos;}else if(!vis[j]&&d[j]==d[pos]+map[pos][j]){pathsum[j]+=pathsum[pos];if(valsum[j]<valsum[pos]+val[j]){valsum[j]=valsum[pos]+val[j];path[j]=pos;}}}}
}void print()
{int i;vector<int>mp;for(i=e;i!=s;i=path[i])mp.push_back(i);	mp.push_back(i);reverse(mp.begin(),mp.end());for(int i=0;i<mp.size();i++){if(i)cout<<' ';cout<<mp[i];}	
}int main()
{cin>>n>>m>>s>>e;for(int i=0;i<n;i++)scanf("%d",&val[i]);init();int x,y,z;for(int i=0;i<m;i++){scanf("%d%d%d",&x,&y,&z);map[x][y]=map[y][x]=z;}jd();printf("%d %d\n",pathsum[e],valsum[e]);print();return 0;
}

(路还很长)。

 

这篇关于L2-001 紧急救援(迪杰斯特拉应用)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/929872

相关文章

亮相WOT全球技术创新大会,揭秘火山引擎边缘容器技术在泛CDN场景的应用与实践

2024年6月21日-22日,51CTO“WOT全球技术创新大会2024”在北京举办。火山引擎边缘计算架构师李志明受邀参与,以“边缘容器技术在泛CDN场景的应用和实践”为主题,与多位行业资深专家,共同探讨泛CDN行业技术架构以及云原生与边缘计算的发展和展望。 火山引擎边缘计算架构师李志明表示:为更好地解决传统泛CDN类业务运行中的问题,火山引擎边缘容器团队参考行业做法,结合实践经验,打造火山

自制的浏览器主页,可以是最简单的桌面应用,可以把它当成备忘录桌面应用

自制的浏览器主页,可以是最简单的桌面应用,可以把它当成备忘录桌面应用。如果你看不懂,请留言。 完整代码: <!DOCTYPE html><html lang="zh-CN"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><ti

Python应用开发——30天学习Streamlit Python包进行APP的构建(9)

st.area_chart 显示区域图。 这是围绕 st.altair_chart 的语法糖。主要区别在于该命令使用数据自身的列和指数来计算图表的 Altair 规格。因此,在许多 "只需绘制此图 "的情况下,该命令更易于使用,但可定制性较差。 如果 st.area_chart 无法正确猜测数据规格,请尝试使用 st.altair_chart 指定所需的图表。 Function signa

气象站的种类和应用范围可以根据不同的分类标准进行详细的划分和描述

气象站的种类和应用范围可以根据不同的分类标准进行详细的划分和描述。以下是从不同角度对气象站的种类和应用范围的介绍: 一、气象站的种类 根据用途和安装环境分类: 农业气象站:专为农业生产服务,监测土壤温度、湿度等参数,为农业生产提供科学依据。交通气象站:用于公路、铁路、机场等交通场所的气象监测,提供实时气象数据以支持交通运营和调度。林业气象站:监测林区风速、湿度、温度等气象要素,为林区保护和

PyTorch模型_trace实战:深入理解与应用

pytorch使用trace模型 1、使用trace生成torchscript模型2、使用trace的模型预测 1、使用trace生成torchscript模型 def save_trace(model, input, save_path):traced_script_model = torch.jit.trace(model, input)<

哺乳细胞重组表达人鼠嵌合抗体:制备与应用

重组抗体是一类具有广泛应用价值的蛋白质,在药物研发和生物医学研究中发挥着重要作用。本文将介绍重组抗体的表达方式,重点关注嵌合抗体制备和哺乳细胞重组表达人鼠嵌合抗体的技术原理和应用。 重组抗体表达的原理和方法 重组抗体表达是通过将人或动物源的免疫球蛋白基因导入表达宿主细胞,并使其表达出特异性抗体蛋白质。常用的表达系统包括细菌、哺乳细胞和真核微生物等。 嵌合抗体制备的步骤和优势 选择适当的抗原

【Qt6.3 基础教程 16】 掌握Qt中的时间和日期:QTimer和QDateTime的高效应用

文章目录 前言QTimer:定时任务的强大工具QTimer的基本用法高级特性:单次定时器 QDateTime:处理日期和时间获取当前日期和时间日期和时间的格式化输出日期和时间计算 用例:创建一个倒计时应用结论 前言 在开发桌面应用程序时,处理时间和日期是一个常见且重要的任务。Qt框架提供了强大的工具来处理与时间相关的功能,其中QTimer和QDateTime是最核心的类。本

基于Spring Boot的企业级应用架构设计

基于Spring Boot的企业级应用架构设计 大家好,我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编,也是冬天不穿秋裤,天冷也要风度的程序猿!今天,我想和大家分享一下基于Spring Boot的企业级应用架构设计,希望对大家有所帮助。 一、Spring Boot概述 Spring Boot是由Pivotal团队提供的全新框架,它简化了Spring应用程序的创建和开发过程。

LoRaWAN在嵌入式网络通信中的应用:打造高效远程监控系统(附代码示例)

引言 随着物联网(IoT)技术的发展,远程监控系统在各个领域的应用越来越广泛。LoRaWAN(Long Range Wide Area Network)作为一种低功耗广域网通信协议,因其长距离传输、低功耗和高可靠性等特点,成为实现远程监控的理想选择。本文将详细介绍LoRaWAN的基本原理、应用场景,并通过一个具体的项目展示如何使用LoRaWAN实现远程监控系统。希望通过图文并茂的讲解,帮助读

一二三应用开发平台应用开发示例(4)——视图类型介绍以及新增、修改、查看视图配置

调整上级属性类型 前面为了快速展示平台的低代码配置功能,将实体文件夹的数据模型上级属性的数据类型暂时配置为文本类型,现在我们调整下,将其数据类型调整为实体,如下图所示: 数据类型需要选择实体,并在实体选择框中选择自身“文件夹” 这时候,再点击生成代码,平台会报错,提示“实体【文件夹】未设置主参照视图”。这是因为文件夹选择的功能页面,同样是基于配置产生的,因为视图我们还没有配置,所以会报错。