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

相关文章

PHP应用中处理限流和API节流的最佳实践

《PHP应用中处理限流和API节流的最佳实践》限流和API节流对于确保Web应用程序的可靠性、安全性和可扩展性至关重要,本文将详细介绍PHP应用中处理限流和API节流的最佳实践,下面就来和小编一起学习... 目录限流的重要性在 php 中实施限流的最佳实践使用集中式存储进行状态管理(如 Redis)采用滑动

深入浅出Spring中的@Autowired自动注入的工作原理及实践应用

《深入浅出Spring中的@Autowired自动注入的工作原理及实践应用》在Spring框架的学习旅程中,@Autowired无疑是一个高频出现却又让初学者头疼的注解,它看似简单,却蕴含着Sprin... 目录深入浅出Spring中的@Autowired:自动注入的奥秘什么是依赖注入?@Autowired

PostgreSQL简介及实战应用

《PostgreSQL简介及实战应用》PostgreSQL是一种功能强大的开源关系型数据库管理系统,以其稳定性、高性能、扩展性和复杂查询能力在众多项目中得到广泛应用,本文将从基础概念讲起,逐步深入到高... 目录前言1. PostgreSQL基础1.1 PostgreSQL简介1.2 基础语法1.3 数据库

Python中的filter() 函数的工作原理及应用技巧

《Python中的filter()函数的工作原理及应用技巧》Python的filter()函数用于筛选序列元素,返回迭代器,适合函数式编程,相比列表推导式,内存更优,尤其适用于大数据集,结合lamb... 目录前言一、基本概念基本语法二、使用方式1. 使用 lambda 函数2. 使用普通函数3. 使用 N

Python中yield的用法和实际应用示例

《Python中yield的用法和实际应用示例》在Python中,yield关键字主要用于生成器函数(generatorfunctions)中,其目的是使函数能够像迭代器一样工作,即可以被遍历,但不会... 目录python中yield的用法详解一、引言二、yield的基本用法1、yield与生成器2、yi

Python多线程应用中的卡死问题优化方案指南

《Python多线程应用中的卡死问题优化方案指南》在利用Python语言开发某查询软件时,遇到了点击搜索按钮后软件卡死的问题,本文将简单分析一下出现的原因以及对应的优化方案,希望对大家有所帮助... 目录问题描述优化方案1. 网络请求优化2. 多线程架构优化3. 全局异常处理4. 配置管理优化优化效果1.

从基础到高阶详解Python多态实战应用指南

《从基础到高阶详解Python多态实战应用指南》这篇文章主要从基础到高阶为大家详细介绍Python中多态的相关应用与技巧,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录一、多态的本质:python的“鸭子类型”哲学二、多态的三大实战场景场景1:数据处理管道——统一处理不同数据格式

Java Stream 的 Collectors.toMap高级应用与最佳实践

《JavaStream的Collectors.toMap高级应用与最佳实践》文章讲解JavaStreamAPI中Collectors.toMap的使用,涵盖基础语法、键冲突处理、自定义Map... 目录一、基础用法回顾二、处理键冲突三、自定义 Map 实现类型四、处理 null 值五、复杂值类型转换六、处理

分布式锁在Spring Boot应用中的实现过程

《分布式锁在SpringBoot应用中的实现过程》文章介绍在SpringBoot中通过自定义Lock注解、LockAspect切面和RedisLockUtils工具类实现分布式锁,确保多实例并发操作... 目录Lock注解LockASPect切面RedisLockUtils工具类总结在现代微服务架构中,分布

Python标准库之数据压缩和存档的应用详解

《Python标准库之数据压缩和存档的应用详解》在数据处理与存储领域,压缩和存档是提升效率的关键技术,Python标准库提供了一套完整的工具链,下面小编就来和大家简单介绍一下吧... 目录一、核心模块架构与设计哲学二、关键模块深度解析1.tarfile:专业级归档工具2.zipfile:跨平台归档首选3.