【动态规划】【图论】【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++**实现。

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

CleanMyMac X 4.14.7帮您安全清理Mac系统垃圾

CleanMyMac X 4.14.7是一款强大的 Mac 清理、加速工具和健康卫士,可以让您的 Mac 再次恢复巅峰性能。 移除大型和旧文件、卸载应用,并删除浪费磁盘空间的无用数据。 5倍 更多可用磁盘空间 CleanMyMac X 4.14.7帮您安全清理Mac系统垃圾 CleanMyMac X 4.14.7一键深度扫描mac系统…

使用GDI画图片生成合成图片并调用打印机进行图片打印

使用GDI画图片生成合成图片并调用打印机进行图片打印 新建窗体应用程序PrinterDemo&#xff0c;将默认的Form1重命名为FormPrinter&#xff0c;添加对 Newtonsoft.Json.dll用于读写Json字符串 zxing.dll&#xff0c;zxing.presentation.dll用于生成条形码&#xff0c;二维码…

ubuntu22.04 安装部署01:禁用内核更新

一、前言 ubunut22.04系统安装以后&#xff0c;内核更新会导致各种各样的问题&#xff0c;因此锁定初始安装环境特别重要&#xff0c;下面介绍如何锁定内核更新。 二、操作方法 2.1 查看可用内核 dpkg --list | grep linux-image dpkg --list | grep linux-headers dpkg --…

橘子学linux调优之工具包的安装

今天在公司无聊的弄服务器&#xff0c;想着有些常用的工具包安装一下&#xff0c;这里就简单记录一下。 一、sysstat的安装和使用 1、安装 我是通过源码的方式安装的&#xff0c;这样的好处在于可以自由选择你的版本&#xff0c;很直观。 直接去github上找到sysstat的地址&a…

这个门禁考勤技术,看了都说好!

在当今数字化时代&#xff0c;考勤管理对于企业、学校、机构等各类组织至关重要。随着科技的不断进步&#xff0c;传统的考勤方式逐渐显露出效率低、安全性差等问题。 因此&#xff0c;为了应对这些挑战&#xff0c;三维人脸考勤系统作为一项创新的解决方案应运而生。 客户案例…

力扣面试题 05.03. 翻转数位(前、后缀和)

Problem: 面试题 05.03. 翻转数位 文章目录 题目描述思路及解法复杂度Code 题目描述 思路及解法 1.将十进制数转换为二进制数&#xff08;每次按位与1求与&#xff0c;并且右移&#xff09;&#xff1b; 2.依次求取二进制数中每一位的前缀1的数量和&#xff0c;和后缀1的数量和…

Java设计模式-责任链模式

责任链模式 一、概述二、结构三、案例实现四、优缺点五、源码解析 一、概述 在现实生活中&#xff0c;常常会出现这样的事例&#xff1a;一个请求有多个对象可以处理&#xff0c;但每个对象的处理条件或权限不同。例如&#xff0c;公司员工请假&#xff0c;可批假的领导有部门…

thinkphp数据批量提交(群发消息)

<form id="edit-form" class="form-horizontal" role="form" data-toggle<

AI克隆自己的声音只需5秒,MockingBird实现AI克隆声音!

一、环境搭建 搭建Anaconda运行环境 搭建Anaconda运行环境请跳转链接查看https://blog.csdn.net/m0_50269929/article/details/136036402安装pytorch pip3 install torch torchvision torchaudio安装ffmpeg 打开官网 https://ffmpeg.org/download.html#get-packages 下载地址…

Leetcode02.05:链表求和

一、题目描述 给定两个用链表表示的整数&#xff0c;每个节点包含一个数位。 这些数位是反向存放的&#xff0c;也就是个位排在链表首部。 编写函数对这两个整数求和&#xff0c;并用链表形式返回结果。 示例&#xff1a; 输入&#xff1a;(7 -> 1 -> 6) (5 -> 9 -…

【数据结构和算法】--- 基于c语言排序算法的实现(1)

目录 一、排序的概念及其应用1.1排序的概念1.2 排序的应用1.3 常见的排序算法 二、插入排序2.1直接插入排序2.2 希尔排序2.2.1 预排序2.2.2 缩小gap2.2.3 小结 三、选择排序3.1 直接选择排序3.2 堆排序 一、排序的概念及其应用 1.1排序的概念 排序&#xff1a; 所谓排序&…