求最短路径的dijkstra算法,可以看成是一个动态规划的方法。
动态规划算法通常基于一个递推公式及一个或多个初始状态。当前子问题的解将由上一次子问题的解推出。
dijkstra虽然没有递推公式,但是满足将大问题分解成子问题,当前问题的解由上一次子问题的解推出。

算法的思想是
使用了三个一维数组,分别是visit[k],pre_node[k],short[k]来分别表示是否经过k点,k点的前驱节点,到达k点的最短距离
初始状态,是所有点出了起点都没经过,所有点的前驱节点都是起点,到达所有点的最短距离是起点直达的距离(没有路径距离就是极大值)。

接着开始循环求子问题。
子问题是先找出没有经过的并且到起点最短距离不是极大值的点i(第一次肯定是离起点最近的点)
如果找不到这个点,跳出循环(结束循环的唯一条件,这样可以避免非联通图出错)
然后分别找出点i的邻点j,判断通过i到j的距离是否小于目前j到起点的距离
如果是,那就更新short[j]和pre_node[k]
最后可以通过pre_node[]来遍历最短路径
代码如下:

int minlength(int (*edge)[7])
{int short_p[7];int pre_node[7];int visit[7];for (int i = 1; i < 7; i++){visit[i] = 0;pre_node[i] = 1;//起点是1,初始化都从1开始,直接从起点到各个点是老路short_p[i] = edge[1][i];}short_p[1] = 0;visit[1] = 1;//for (int v = 0; v < 7; v++){//无法避免不是联通图的情况while (1){int min = max_n;int k = -1;for (int i = 2; i < 7; i++){//先找出没进过的并且离起点最近的点if (!visit[i] && short_p[i] < min){min = short_p[i];k = i;}}if (k == -1)break;//找不到就跳出去,因为可能图不连通elsevisit[k] = 1;for (int ii = 2; ii < 7; ii++){//以上面找到的点为基准,找出相邻没过的点,检查过这个点到相邻点近还是老路近if (!visit[ii] && edge[k][ii] + min < short_p[ii]){short_p[ii] = edge[k][ii] + min;pre_node[ii] = k;//更改前节点}}}return 0;
}
int main()
{int edge[7][7] = { max_n };for (int i = 0; i < 7; i++){for (int j = 0; j < 7; j++)edge[i][j] = max_n;}edge[1][2] = 8;edge[1][5] = 3;edge[2][3] = 1;edge[2][5] = 4;edge[2][6] = 5;edge[3][4] = 4;edge[3][6] = 1;edge[4][6] = 3;edge[5][6] = 2;for (int i = 0; i < 7; i++){for (int j = i+1; j < 7; j++)edge[j][i] = edge[i][j];}minlength(edge);
}

上面只有距离唯一一个条件,是一维的,逻辑比较简单
如果每条路径还需要收过路费,就是一个二维的动态规划问题。

问题变为了
到达在符合经费预算的情况下到达目标点的最短距离
或者到达目标点花费最少
算法思想还是使用三个数组,不过是2纬数组,第二维的下标表示的是经费余额
visit[i][j]是否到达节点i并且经费余额为j的情况
short[i][j]表示在经费余额为j的情况下,到达节点i的最短距离
pair<int,int>[i][j]用来存放当前情况的前一个情况(节点结合余额)

初始状态
visit[i][j]全没经历过 visit[v0][money]=1 v0为原点,money为所有预算
pair[i][j]设为初始值,和起点相邻的并且预算够过路费的标为 (v0,money), 起点的前驱还是起点
其余节点都是起点,余额为-1
short[i][j]都为极大值 short[v0][money] = 0 ,起点本身 距离0,且没花钱

开始循环求解子问题
考虑所有的点以及所有的花费(余额>=0)的情况,
找到满足预算路径最短的点(小于极大值)(一开始是起点的邻点,不一定是最近的点)
如果找不到就跳出循环
找到了 标记为点k,余额为p
找出所有与点k相邻的点ii,
如果余额允许到点ii AND !visit[ii][到达ii后的余额](该情况没经历过) AND 起点经过点k到点ii的距离 < 同等花费下原先的距离(short[ii][p-k到ii的花费])
更新同等花费下原先的距离
更新pre_node[][]

代码如下:

#include<iostream>
#include<algorithm>
#include<stack>
using namespace std;const int max_n = 65535;int short_p[7][21];//short_p[i][j]表示点i到起点,余额为j的最短距离
int visit[7][21];
int edge[7][7], mny[7][7];
std::pair<int, int> pre_node[7][21];
int minlength(int money)
{for (int i = 1; i < 7; i++){for (int j = 0; j < 21; j++){visit[i][j] = 0;short_p[i][j] = max_n;pre_node[i][j]=make_pair(1, -1);}if (money - mny[1][i] >= 0){short_p[i][money - mny[1][i]] = edge[1][i];pre_node[i][money - mny[1][i]] = make_pair(1, money);}}visit[1][money] = 1;//标记起点short_p[1][money] = 0;//距起点距离为0,没花钱pre_node[1][money] = make_pair(1, money);while (true){int min = max_n;int k = -1, p = -1;for (int i = 2; i < 7; i++){//先找出没进过的并且离起点最近的点for (int j = 0; j < money; j++){if (!visit[i][j] && short_p[i][j] < min){min = short_p[i][j];k = i;p = j;}}}if (k == -1 || p == -1)break;elsevisit[k][p] = 1;for (int ii = 2; ii < 7; ii++){//以上面找到的点为基准,找出相邻没过的点,检查过这个点到相邻点近还是老路近//又足够的余额去相邻的点,   并且没有遇到过同类情况   且             距离更短if ((p - mny[k][ii] > 0) && !visit[ii][p - mny[k][ii]] && edge[k][ii] + min < short_p[ii][p - mny[k][ii]]){short_p[ii][p - mny[k][ii]] = edge[k][ii] + min;pre_node[ii][p - mny[k][ii]] = make_pair(k, p);//更改前节点}}}return 0;
}int min_cost_pathprint(int node, int money)
{if (node > 6 || node < 1)return -1;cout << "到节点 " << node << " 花费最少为: ";int i = money;for (; i >= 0; i--){if (short_p[node][i] < max_n)break;}cout << money - i << " 元" << endl;return i;
}int min_lengthpath(int node, int money)
{if (node > 6 || node < 1)return -1;cout << "到节点 " << node << " 最短距离为: ";int min = max_n;int k;for (int i = 0; i <= money; i++){if (short_p[node][i] < min){min = short_p[node][i];k = i;}}cout << min << endl;return k;
}void pathprint(int node, int last)
{cout << "路径为:";std::pair<int, int> pathpair;stack<std::pair<int, int>> path;int dst = node, mm = last;do{pathpair = make_pair(dst, mm);path.push(pathpair);int dst1 = pre_node[dst][mm].first;int mm1 = pre_node[dst][mm].second;dst = dst1;mm = mm1;} while (pathpair.first != 1);while (path.size() > 1){cout << '<' << path.top().first << ' ' << path.top().second << '>' << ' ';path.pop();}cout << '<' << path.top().first << ' ' << path.top().second << '>' << endl;
}int main()
{for (int i = 0; i < 7; i++){for (int j = 0; j < 7; j++){edge[i][j] = max_n;mny[i][j] = max_n;}}//距离edge[1][2] = 8;edge[1][5] = 3;edge[2][3] = 1;edge[2][5] = 4;edge[2][6] = 5;edge[3][4] = 4;edge[3][6] = 1;edge[4][6] = 3;edge[5][6] = 2;//过路费mny[1][2] = 1;mny[1][5] = 3;mny[2][3] = 7;mny[2][5] = 6;mny[2][6] = 2;mny[3][4] = 2;mny[3][6] = 4;mny[4][6] = 3;mny[5][6] = 5;for (int i = 0; i < 7; i++){for (int j = i + 1; j < 7; j++){edge[j][i] = edge[i][j];mny[j][i] = mny[i][j];}}int money = 20;minlength(money);int t1 = min_lengthpath(4,money);if (t1 >= 0)pathprint(4, t1);int t2 = min_cost_pathprint(4, money);if (t2 >= 0)pathprint(4, t2);return 0;
}
/*收过路费 二维地杰斯特拉 结束*/

欢迎交流

最短路径和最少花费问题--动态规划相关推荐

  1. 1326. 灌溉花园的最少水龙头数目 动态规划

    1326. 灌溉花园的最少水龙头数目 在 x 轴上有一个一维的花园.花园长度为 n,从点 0 开始,到点 n 结束. 花园里总共有 n + 1 个水龙头,分别位于 [0, 1, ..., n] . 给 ...

  2. hdu 1257最少拦截系统 动态规划

    最少拦截系统 Time Limit : 2000/1000ms (Java/Other)   Memory Limit : 65536/32768K (Java/Other) Problem Desc ...

  3. 2.某服装店进行促销活动,一件上衣原价90元,裤子原价45元,现一套120元。 如果我买m套上衣和n套裤子,最少花费多少钱?

    #include <stdio.h> int main(int argc, const char *argv[]) {     int m=0,n=0,money;     scanf(& ...

  4. LeetCode 2086. 从房屋收集雨水需要的最少水桶数 -- 动态规划

    从房屋收集雨水需要的最少水桶数 中等 26 相关企业 给你一个下标从 0 开始的字符串 street .street 中每个字符要么是表示房屋的 'H' ,要么是表示空位的 '.' . 你可以在 空位 ...

  5. 数据结构实验之图论七:驴友计划

    题目描述 做为一个资深驴友,小新有一张珍藏的自驾游线路图,图上详细的标注了全国各个城市之间的高速公路距离和公路收费情况,现在请你编写一个程序,找出一条出发地到目的地之间的最短路径,如果有多条路径最短, ...

  6. java 动态规划求最短路径_使用分支界定和动态规划解决最短路径问题(原)

    算法的思想: 分析题目要求,我们可以得知:算法要实现找到一条花费在1500元以下的最短的路径.其中这里面涉及两个变量,一个是路径的长度,要求最短.一个是花费,要求不大于1500元.基于这两个变量的不同 ...

  7. 【ECNU OJ 3373】 骑士游戏 最短路径+动态规划

    Problem 3373 骑士游戏 长期的宅男生活中,JYY 又挖掘出了一款 RPG 游戏.在这个游戏中 JYY 会扮演一个英勇的骑士,用他手中的长剑去杀死入侵村庄的怪兽. 在这个游戏中,JYY 一共 ...

  8. 数据结构—图及其应用(交通问题,实现最短路径、最短时间、最少费用查询)

    数据结构-图及其应用(交通问题,实现最短路径.最短时间.最少费用查询) 1.任务描述 (1).任务: 设计一个城市交通咨询模拟系统,利用该系统实现至少两种最优决策:最短路程到达.最省时到达等线路规划. ...

  9. 图论动态规划算法——Floyd最短路径

    前言 推出一个新系列,<看图轻松理解数据结构和算法>,主要使用图片来描述常见的数据结构和算法,轻松阅读并理解掌握.本系列包括各种堆.各种队列.各种列表.各种树.各种图.各种排序等等几十篇的 ...

  10. 广度优先搜索 宽度优先搜索 迷宫问题 最短路径 最少操作 由近及远 队列

    广度优先搜索,也叫宽度优先搜索,从开始状态,到第一次能到达的状态,再从第一次能到达的状态到下一个能到达的状态,直到探索所有可到达的状态,其时间复杂度为O(状态数×转移的方式). 广度优先搜索使用了队列 ...

最新文章

  1. 微软亚研院20周年独家撰文:数据智能的现在与未来
  2. 想 new 个对象过七夕,她却抛了异常
  3. ObjC load与initialize 简析
  4. 05NumPy--5.1多维数组
  5. IDEA(2018)连接MySQL数据库失败的解决方法(报错08001)
  6. 用python写一个简单的web服务器
  7. Spring中利用配置文件和 value注入属性值
  8. GoldenGate新增表
  9. java 类 引用数组对象_Java 方法重载与引用数组类型
  10. viper4android 机顶盒,利用VIPer53封装上系统实现经济型机顶盒供电
  11. Java 度分秒转经纬度,经纬度转度分秒,度分转经纬度,经纬度转度分
  12. 本地计算机的硬件基本配置信息,Windows7系统如何查看硬件的基本配置
  13. 关闭windows电脑 ctrl +alt +方向键旋转屏幕快捷键
  14. vue—递归组件(vue组件name的作用之一)
  15. 深度linux卡在logo,记录一次深度deepin开机卡logo解决方案
  16. 在python里调用c++的DLL出现Windows Error -529697949
  17. 用Tab键的程序员为什么瞧不起用Space键的?
  18. 保利威荣获「年度最佳直播服务商」!引领视频直播行业创新发展
  19. ansible 命令只执行一次
  20. 让iframe高度伸缩自如没有滚动条

热门文章

  1. DITHER 抖动算法(转载)
  2. Linux头文件 C/C++头文件
  3. Getting Real ——把握现实
  4. wifi共享大师,去除弹窗广告。
  5. python print什么意思_python中print有什么用
  6. crx什么意思_CRX文件怎么打开-CRX是什么格式-CRX文件是什么意思-腾牛网
  7. JVM学习笔记(12) 垃圾回收-垃圾回收相关算法
  8. 利用Tween让动画更平滑(补间动画)
  9. 判断一个字符串能否通过添加一个字符变成回文串
  10. ROS2 C++ Subscriber Publisher 订阅发布例子