【动态规划】【图论】【C++算法】1928规定时间内到达终点的最小花费

作者推荐

【动态规划】【状态压缩】【2次选择】【广度搜索】1494. 并行课程 II

本文涉及知识点

动态规划汇总

LeetCode1928. 规定时间内到达终点的最小花费

一个国家有 n 个城市,城市编号为 0 到 n - 1 ,题目保证 所有城市 都由双向道路 连接在一起 。道路由二维整数数组 edges 表示,其中 edges[i] = [xi, yi, timei] 表示城市 xi 和 yi 之间有一条双向道路,耗费时间为 timei 分钟。两个城市之间可能会有多条耗费时间不同的道路,但是不会有道路两头连接着同一座城市。
每次经过一个城市时,你需要付通行费。通行费用一个长度为 n 且下标从 0 开始的整数数组 passingFees 表示,其中 passingFees[j] 是你经过城市 j 需要支付的费用。
一开始,你在城市 0 ,你想要在 maxTime 分钟以内 (包含 maxTime 分钟)到达城市 n - 1 。旅行的 费用 为你经过的所有城市 通行费之和 (包括 起点和终点城市的通行费)。
给你 maxTime,edges 和 passingFees ,请你返回完成旅行的 最小费用 ,如果无法在 maxTime 分钟以内完成旅行,请你返回 -1 。
示例 1:
输入:maxTime = 30, edges = [[0,1,10],[1,2,10],[2,5,10],[0,3,1],[3,4,10],[4,5,15]], passingFees = [5,1,2,20,20,3]
输出:11
解释:最优路径为 0 -> 1 -> 2 -> 5 ,总共需要耗费 30 分钟,需要支付 11 的通行费。
示例 2:
输入:maxTime = 29, edges = [[0,1,10],[1,2,10],[2,5,10],[0,3,1],[3,4,10],[4,5,15]], passingFees = [5,1,2,20,20,3]
输出:48
解释:最优路径为 0 -> 3 -> 4 -> 5 ,总共需要耗费 26 分钟,需要支付 48 的通行费。
你不能选择路径 0 -> 1 -> 2 -> 5 ,因为这条路径耗费的时间太长。
示例 3:
输入:maxTime = 25, edges = [[0,1,10],[1,2,10],[2,5,10],[0,3,1],[3,4,10],[4,5,15]], passingFees = [5,1,2,20,20,3]
输出:-1
解释:无法在 25 分钟以内从城市 0 到达城市 5 。
提示:
1 <= maxTime <= 1000
n == passingFees.length
2 <= n <= 1000
n - 1 <= edges.length <= 1000
0 <= xi, yi <= n - 1
1 <= timei <= 1000
1 <= passingFees[j] <= 1000
图中两个节点之间可能有多条路径。
图中不含有自环。

动态规划

路径中不会有重复节点,否则去掉环,用时更少,过路费更少或不变。

动态规划的状态表示

dp[i][j] 表示 消耗j单位时间到达i城市的最小过路非。所有相同时间的状态全部更新完时间复杂度是O(n),时间数是maxTime。故总时间复杂度是:O(n*maxTime)。

动态规划的转移方程

前置状态转移后置状态。
dp[i][j] 更 新 k 和 i 连接 \Large更新 _{k和i连接} ki连接 dp[k][j+ik需要的时间] =min(,dp[i][j]+pass[k]

动态规划的初始值

dp[0][0]=第一个城市的过路费 其它状态全部为2e6。

动态规划的填表顺序

时间从0到大。

动态规划的返回值

dp.back()的最小值。

代码

class Solution {
public:
	int minCost(int maxTime, vector<vector<int>>& edges, vector<int>& passingFees) {
		m_c = passingFees.size();
		CNeiBo3 neiBo(m_c, edges,false);
		vector<vector<int>> dp(m_c, vector<int>(maxTime + 1, m_iNotMay));
		dp[0][0] = passingFees[0];
		for (int time = 0; time < maxTime; time++)
		{
			for (int pos = 0; pos < m_c; pos++)
			{
				for (const auto& [next,useTime] : neiBo.m_vNeiB[pos])
				{
					const int newTime = time + useTime;
					if (newTime <= maxTime)
					{
						const int newFees = dp[pos][time] + passingFees[next];
						if (newFees < dp[next][newTime])
						{
							dp[next][newTime] = newFees;
						}
					}
				}
			}
		}
		const int iMin = *std::min_element(dp.back().begin(), dp.back().end());
		return (iMin >= m_iNotMay) ? -1 : iMin;
	}
	int m_c;
	const int m_iNotMay = 2000'000;
};

测试用例

template<class T>
void Assert(const T& t1, const T& t2)
{
	assert(t1 == t2);
}

template<class T>
void Assert(const vector<T>& v1, const vector<T>& v2)
{
	if (v1.size() != v2.size())
	{
		assert(false);
		return;
	}
	for (int i = 0; i < v1.size(); i++)
	{
		Assert(v1[i], v2[i]);
	}

}

int main()
{	
	int maxTime;
	vector<vector<int>> edges;
	vector<int> passingFees;
	{
		Solution sln;
		maxTime = 30, edges = { {0,1,10},{1,2,10},{2,5,10},{0,3,1},{3,4,10},{4,5,15} }, passingFees = { 5,1,2,20,20,3 };
		auto res = sln.minCost(maxTime, edges, passingFees);
		Assert(res,11);
	}

	{
		Solution sln;
		maxTime = 29, edges = { {0,1,10},{1,2,10},{2,5,10},{0,3,1},{3,4,10},{4,5,15} }, passingFees = { 5,1,2,20,20,3 };
		auto res = sln.minCost(maxTime, edges, passingFees);
		Assert(res, 48);
	}

	{
		Solution sln;
		maxTime = 25, edges = { {0,1,10},{1,2,10},{2,5,10},{0,3,1},{3,4,10},{4,5,15} }, passingFees = { 5,1,2,20,20,3 };
		auto res = sln.minCost(maxTime, edges, passingFees);
		Assert(res, -1);
	}
}

2023年2月版

class Solution {
public:
int minCost(int maxTime, vector<vector>& edges, vector& passingFees) {
m_c = passingFees.size();
m_mDirectTime.resize(m_c);
for (const auto& v : edges)
{
if (v[2] > maxTime)
{
continue;
}
if (0 != m_mDirectTime[v[0]][v[1]] )
{
if (m_mDirectTime[v[0]][v[1]] < v[2])
{
continue;
}
}
m_mDirectTime[v[0]][v[1]] = v[2];
m_mDirectTime[v[1]][v[0]] = v[2];
}
dp.assign(maxTime+1, vector(m_c, m_iNotMay));
dp[0][0] = passingFees[0];
for (int iTime = 0; iTime <= maxTime; iTime++)
{
for (int iPos = 0; iPos < m_c; iPos++)
{
const int& iCurFees = dp[iTime][iPos];
if (m_iNotMay == iCurFees)
{
continue;
}
for (auto it : m_mDirectTime[iPos] )
{
const int iNewTime = iTime + it.second;
if (iNewTime > maxTime)
{
continue;
}
int& iNewFees = dp[iNewTime][it.first];
iNewFees = min(iNewFees, iCurFees + passingFees[it.first]);
}
}
}
int iMinFeel = INT_MAX;
for (auto& v : dp)
{
iMinFeel = min(iMinFeel, v[m_c - 1]);
}
return ( m_iNotMay == iMinFeel) ? -1 : iMinFeel;
}
int m_c;
vector<vector> dp;
vector<std::unordered_map<int, int>> m_mDirectTime;
const int m_iNotMay = 1000 * 1000 * 1000;

};

2023年7月版

class Solution {
public:
int minCost(int maxTime, vector<vector>& edges, vector& passingFees) {
m_c = passingFees.size();
vector<vector> vTimeNodeToMinCost(maxTime + 1, vector(m_c, INT_MAX));
vTimeNodeToMinCost[0][0] = passingFees[0];
for (int time = 1; time <= maxTime; time++)
{
for (const auto& v : edges)
{
Do(v[0], v[1], v[2], time, vTimeNodeToMinCost, passingFees);
Do(v[1], v[0], v[2], time, vTimeNodeToMinCost, passingFees);
}
}
int iMinCost = INT_MAX;
for (const auto& v : vTimeNodeToMinCost)
{
iMinCost = min(iMinCost, v.back());
}
return (INT_MAX == iMinCost) ? -1 : iMinCost;
}
void Do(int pre, int cur, int iUseTime,int time, vector<vector>& vTimeNodeToMinCost, const vector& passingFees)
{
int preTime = time - iUseTime;
if (preTime < 0)
{
return;
}
const int preMinCost = vTimeNodeToMinCost[preTime][pre];
if (INT_MAX == preMinCost)
{
return;
}
vTimeNodeToMinCost[time][cur] = min(vTimeNodeToMinCost[time][cur], preMinCost + passingFees[cur]);
}

int m_c;
vector < vector<pair<int, int>>> m_vNeiB;
int m_iMinCost = INT_MAX;
int m_iMaxTime;

};

2023年9月

class Solution {
public:
int minCost(int maxTime, vector<vector>& edges, vector& passingFees) {
m_iCityNum = passingFees.size();
std::unordered_map<int, int> mNodeNodeToTime[1001];
for (const auto& v : edges)
{
if (!mNodeNodeToTime[v[0]].count(v[1]) || (mNodeNodeToTime[v[0]][v[1]] > v[2]))
{
mNodeNodeToTime[v[0]][v[1]] = v[2];
mNodeNodeToTime[v[1]][v[0]] = v[2];
}
}
for (int i = 0; i < m_iCityNum; i++)
{
m_vNeiBo[i] = vector<pair<int, int>>(mNodeNodeToTime[i].begin(), mNodeNodeToTime[i].end());
}
return Do(maxTime, passingFees);
}
int Do(int maxTime, vector& passingFees)
{
vector vMinFee(m_iCityNum,INT_MAX);
std::priority_queue<tuple<int, int, int>, vector<tuple<int, int, int>>, std::greater<>> minHeap;
minHeap.emplace(0, 0, passingFees[0]);//总耗时,当前城市,最小消耗
while (minHeap.size())
{
const auto [time, city, fee] = minHeap.top();
minHeap.pop();
if (vMinFee[city] <= fee)
{
continue;
}
else
{
vMinFee[city] = fee;
}
for (const auto& [next, useTime] : m_vNeiBo[city])
{
const int iNewTime = time + useTime;
if (iNewTime > maxTime)
{
continue;
}
const int iNewFee = fee + passingFees[next];
minHeap.emplace(iNewTime, next, iNewFee);
}
}
return ( INT_MAX == vMinFee[m_iCityNum-1] ) ? -1 : vMinFee[m_iCityNum - 1];
}
vector<pair<int, int>> m_vNeiBo[1001];
int m_iCityNum;
};

扩展阅读

视频课程

有效学习:明确的目标 及时的反馈 拉伸区(难度合适),可以先学简单的课程,请移步CSDN学院,听白银讲师(也就是鄙人)的讲解。
https://edu.csdn.net/course/detail/38771

如何你想快速形成战斗了,为老板分忧,请学习C#入职培训、C++入职培训等课程
https://edu.csdn.net/lecturer/6176

相关

下载

想高屋建瓴的学习算法,请下载《喜缺全书算法册》doc版
https://download.csdn.net/download/he_zhidan/88348653

我想对大家说的话
闻缺陷则喜是一个美好的愿望,早发现问题,早修改问题,给老板节约钱。
子墨子言之:事无终始,无务多业。也就是我们常说的专业的人做专业的事。
如果程序是一条龙,那算法就是他的是睛

测试环境

操作系统:win7 开发环境: VS2019 C++17
或者 操作系统:win10 开发环境: VS2022 C++17
如无特殊说明,本算法用**C++**实现。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/373539.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Java设计模式大全:23种常见的设计模式详解(一)

本系列文章简介&#xff1a; 设计模式是在软件开发过程中&#xff0c;经过实践和总结得到的一套解决特定问题的可复用的模板。它是一种在特定情境中经过验证的经验和技巧的集合&#xff0c;可以帮助开发人员设计出高效、可维护、可扩展和可复用的软件系统。设计模式提供了一种在…

VS编译器对scanf函数不安全报错的解决办法(详细步骤)

&#x1f4da;博客主页&#xff1a;爱敲代码的小杨. ✨专栏&#xff1a;《Java SE语法》 | 《数据结构与算法》 | 《C生万物》 ❤️感谢大家点赞&#x1f44d;&#x1f3fb;收藏⭐评论✍&#x1f3fb;&#xff0c;您的三连就是我持续更新的动力❤️ &#x1f64f;小杨水平有…

第5节、S曲线加减速转动【51单片机+L298N步进电机系列教程】

↑↑↑点击上方【目录】&#xff0c;查看本系列全部文章 摘要&#xff1a;本节介绍步进电机S曲线相关内容&#xff0c;总共分四个小节讨论步进电机S曲线相关内容 5-1、S曲线加减速简介   根据上节内容&#xff0c;步进电机每一段的速度可以任意设置&#xff0c;但是每一段的…

【教程】ESP32-CAM使用WiFi和MQTT

转载请注明出处&#xff1a;小锋学长生活大爆炸[xfxuezhang.cn] 连接MQTT 1、先安装库 2、默认你已有MQTT服务器 3、编写代码(跳过WiFi连接部分) #include <PubSubClient.h>// MQTT server details const char* mqtt_server "xxxxx.cn"; const int mqtt_po…

Spring Boot整合MyBatis Plus实现基本CRUD与高级功能

文章目录 1. 引言2. 项目搭建与依赖配置2.1 添加MyBatis Plus依赖2.2 配置数据源与MyBatis Plus 3. 实现基本CRUD功能3.1 创建实体类3.2 创建Mapper接口3.3 实现Service层3.4 控制器实现 4. 高级功能实现4.1 自动填充功能4.2 乐观锁功能4.3 逻辑删除功能 5. 拓展&#xff1a;My…

Kafka SASL_SSL双重认证

文章目录 1. 背景2. 环境3. 操作步骤3.1 生成SSL证书3.2 配置zookeeper认证3.3 配置kafka安全认证3.4 使用kafka客户端进行验证3.5 使用Java端代码进行认证 1. 背景 kafka提供了多种安全认证机制&#xff0c;主要分为SASL和SSL两大类。 SASL&#xff1a; 是一种身份验证机制&…

计算机网络——新型网络架构:SDN/NFV

1. 传统节点与SDN节点 1.1 传统节点(Traditional Node) 这幅图展示了传统网络节点的结构。在这种设置中&#xff0c;控制层和数据层是集成在同一个设备内。 以太网交换机&#xff1a;在传统网络中&#xff0c;交换机包括控制层和数据层&#xff0c;它不仅负责数据包的传输&…

【CSS】margin塌陷和margin合并及其解决方案

【CSS】margin塌陷和margin合并及其解决方案 一、解决margin塌陷的问题二、避免外边距margin重叠&#xff08;margin合并&#xff09; 一、解决margin塌陷的问题 问题&#xff1a;当父元素包裹着一个子元素的时候&#xff0c;当给子元素设置margin-top:100px&#xff0c;此时不…

vue2 自定义指令 v-highlight 文本高亮显示分享

简单分享一个文本高亮显示的自定义指令&#xff0c;主要分两部分&#xff1a; 1、代码实现&#xff1a;在 main.js 文件中添加一个自定义指令&#xff0c;实现搜索时文本高亮显示&#xff0c;代码如下&#xff1a; const highlightText (el, searchText) > {const textCo…

详细关于如何解决mfc140.dll丢失的步骤,有效修复mfc140.dll文件丢失的问题。

mfc140.dll文件是Microsoft Visual Studio 2015程序集之一&#xff0c;它包含用于支持多种功能的代码和库。当这个mfc140.dll文件丢失时&#xff0c;可能会导致相关程序运行出错甚至无法运行。很多用户可能会遇到mfc140.dll丢失的问题&#xff0c;但是这并不是不可解决的困难。…

2024 年十大 Vue.js UI 库

Vue.js 是一个流行的 JavaScript 框架&#xff0c;它在前端开发者中越来越受欢迎&#xff0c;以其简单、灵活和易用性而闻名。 Vue.js 如此受欢迎的原因之一是它拥有庞大的 UI 库生态系统。 这些库为开发人员提供了预构建的组件和工具&#xff0c;帮助他们快速高效地构建漂亮…

PCIE 参考时钟架构

一、PCIe架构组件 首先先看下PCIE架构组件&#xff0c;下图中主要包括&#xff1a; ROOT COMPLEX (RC) (CPU); PCIE PCI/PCI-X Bridge; PCIE SWITCH; PCIE ENDPOINT (EP) (pcie设备); BUFFER; 各个器件的时钟来源都是由100MHz经过Buffer后提供。一个PCIE树上最多可以有256个…

如何在Termux中使用Hexo结合内网穿透工具实现远程访问本地博客站点

文章目录 前言 1.安装 Hexo2.安装cpolar3.远程访问4.固定公网地址 前言 Hexo 是一个用 Nodejs 编写的快速、简洁且高效的博客框架。Hexo 使用 Markdown 解析文章&#xff0c;在几秒内&#xff0c;即可利用靓丽的主题生成静态网页。 下面介绍在Termux中安装个人hexo博客并结合…

考研数据结构笔记(1)

数据结构&#xff08;1&#xff09; 数据结构在学什么&#xff1f;数据结构的基本概念基本概念三要素逻辑结构集合线性结构树形结构图结构 物理结构&#xff08;存储结构&#xff09;顺序存储链式存储索引存储散列存储重点 数据的运算 算法的基本概念什么是算法算法的五个特性有…

LeetCode、198. 打家劫舍【中等,一维线性DP】

文章目录 前言LeetCode、198. 打家劫舍【中等&#xff0c;一维线性DP】题目及分类思路线性DP&#xff08;一维&#xff09; 资料获取 前言 博主介绍&#xff1a;✌目前全网粉丝2W&#xff0c;csdn博客专家、Java领域优质创作者&#xff0c;博客之星、阿里云平台优质作者、专注…

记一次页面接口502问题:“502 Bad Gateway”

接收别人的项目进行迭代&#xff0c;项目部署到服务器上之后&#xff0c;有一个接口数据刷不出来&#xff0c;一直502 后来联想到网关的问题&#xff0c;想通过设置白名单的方式解决&#xff0c;设置之后依旧不行。 查看nginx日志发现报错&#xff1a; *169 connect() failed …

vue - 指令(一)

看文章可以得到什么&#xff1f; 1.可以快速的了解并会使用vue的指令 2.可以加深你对vue指令的理解&#xff0c;知道每个指令代表什么功能​​​​​​​ 目录 什么是vue的指令&#xff1f;​​​​​​​ vue常见指令的使用 v-html v-show v-if v-else 和v-else-…

Redis(三)(实战篇)

查漏补缺 1.spring 事务失效 有时候我们需要在某个 Service 类的某个方法中&#xff0c;调用另外一个事务方法&#xff0c;比如&#xff1a; Service public class UserService {Autowiredprivate UserMapper userMapper;public void add(UserModel userModel) {userMapper.…

QMUI_Android:提升Android开发效率与质量的利器

QMUI_Android&#xff1a;提升Android开发效率与质量的利器 在Android应用开发过程中&#xff0c;开发者常常面临着重复编写基础组件和处理兼容性问题的挑战&#xff0c;这不仅耗费时间&#xff0c;也降低了开发效率。为了解决这一问题&#xff0c;Tencent推出了QMUI_Android框…

Linux-3 进程概念(三)

1.环境变量 1.1基本概念 环境变量(environment variables)一般是指在操作系统中用来指定操作系统运行环境的一些参数 如&#xff1a;我们在编写C/C代码的时候&#xff0c;在链接的时候&#xff0c;从来不知道我们的所链接的动态静态库在哪里&#xff0c;但是照样可以链接成功…