楔子

long long ago就已经知道了Floyd算法,关键代码就4行,也容易记住,上上周又看到了Floyd,都说是动态规划,所以特意去学了一圈动态规划,今天终于又回到了它

状态方程:

d[k][i][j]定义:“只能使用第1号到第k号点作为中间媒介时,点i到点j之间的最短路径长度。”
在动态规划算法中,处于首要位置、且也是核心理念之一的就是状态的定义
这个大家喜欢把它叫做“松弛操作”,也就是relax
对于d[k][i][j](即使用1号到k号点中的所有点作为中间媒介时,i和j之间的最短路径),可以分为两种情况:

1)i到j的最短路不经过k;(
2)i到j的最短路经过了k。不经过点k的最短路情况下,d[k][i][j]=d[k-1][i][j]。经过点k的最短路情况下,d[k][i][j]=d[k-1][i][k]+d[k-1][k][j]。

因此,综合上述两种情况,便可以得到Floyd算法的动态转移方程:
d[k][i][j] = min(d[k-1][i][j], d[k-1][i][k]+d[k-1][k][j])(k,i,j∈[1,n])

初始条件:d[0][i][j]=w(i, j),d[k][0][j]=0,d[k][i][0]=0

原始的实现如下:

# d[k][i][j] = min(d[k-1][i][j], d[k-1][i][k]+d[k-1][k][j])(k,i,j∈[1,n])
import numpy as np
def floyd_original(graph):vertex_num = len(graph)list = np.full((vertex_num+1,vertex_num+1,vertex_num+1),np.inf)list[:,0,:] = 0list[:,:,0] = 0for i in range(1,vertex_num+1):for j in range(1,vertex_num+1):list[0,i,j] = graph[i-1,j-1]for k in range(1,vertex_num+1):for i in range(1,vertex_num+1):for j in range(1,vertex_num+1):list[k,i,j] = min(list[k-1,i,j],list[k-1,i,k]+list[k-1,k,j])return list[vertex_num,1:,1:]

观察DP数组,可以做空间优化,类似于背包问题使用滚动数组优化:

1、d[k][i][j]只与d[k-1][i][j], d[k-1][i][k]+d[k-1][k][j]有关,也就是只和d[k-1],那么我们就可以只用一个二维数组代替三维的数组;

2、然后看我们是否需要注意遍历这个二维数组的顺序(例如01背包问题需要逆序遍历才能保证用的数据是上一层的,完全背包需要顺序遍历才能保证用的数据是更新后的这一层的),假如采取顺序的话,d[k-1][i][j]这个没问题,d[k-1][i][k]+d[k-1][k][j]这个k永远是小于或者等于i的,所以d[k-1][i][k]+d[k-1][k][j]取的是应该是更新后的数据,他们在已更新的区域里,那不是不能使用滚动数组了?但是事实已经证明可以这么用,后来发现一个解释:

3、有这样一条重要的性质,dp[k-1][i][k]和dp[k-1][k][j]是不会在第k阶段改变大小的。也就是说,凡是和k节点相连的边,在第k阶段的值都不会变。如何简单证明呢?我们可以把j=k代入之前的d[k][i][j]=min(d[k-1][i][j], d[k-1][i][k]+d[k-1][k][j])方程中,即:

d[k][i][k]
= min(d[k-1][i][k], d[k-1][i][k]+d[k-1][k][k])= min(d[k-1][i][k], d[k-1][i][k]+0)= d[k-1][i][k]

也就是说在第k-1阶段和第k阶段,点i和点k之间的最短路径长度是不变的。相同可以证明,在这两个阶段中,点k和点j之间的的最短路径长度也是不变的。因此,对于使用滚动数组的转移方程d[i][j] = min(d[i][j], d[i][k]+d[k][j])来说,赋值号右侧的d[i][j], d[i][k]和d[k][j]的值都是上一阶段(k-1阶段)的值,可以放心地被用来计算第k阶段时d[i][j]的值。
有没有很坑? 绕了一圈又回到不熟悉的东西上去了
仔细看一遍上述的公式就懂了。
所以我们可以使用滚动数组来优化空间。

实现如下:

import numpy as np
def floyd(graph):vertex_num = len(graph)   list = np.zeros((vertex_num+1,vertex_num+1))for i in range(1,vertex_num+1):for j in range(1,vertex_num+1):list[i,j] = graph[i-1,j-1]for k in range(1,vertex_num+1):for i in range(1,vertex_num+1):for j in range(1,vertex_num+1):list[i,j] = min(list[i,j],list[i,k]+list[k,j])return list[1:,1:]

运行结果

#%%
graph = np.full((7,7),np.inf)
graph[0,:3] = [0,1,2]
graph[1,:4] = [1,0,3,4]
graph[2,:4] = [2,3,0,6]
graph[3,1:5] = [4,6,0,7]
graph[4,3:6] = [7,0,9]
graph[5,4:7] = [9,0,10]
graph[6,5:7] = [10,0]print floyd_original(graph)print floyd(graph)[[ 0.  1.  2.  5. 12. 21. 31.][ 1.  0.  3.  4. 11. 20. 30.][ 2.  3.  0.  6. 13. 22. 32.][ 5.  4.  6.  0.  7. 16. 26.][12. 11. 13.  7.  0.  9. 19.][21. 20. 22. 16.  9.  0. 10.][31. 30. 32. 26. 19. 10.  0.]][[ 0.  1.  2.  5. 12. 21. 31.][ 1.  0.  3.  4. 11. 20. 30.][ 2.  3.  0.  6. 13. 22. 32.][ 5.  4.  6.  0.  7. 16. 26.][12. 11. 13.  7.  0.  9. 19.][21. 20. 22. 16.  9.  0. 10.][31. 30. 32. 26. 19. 10.  0.]]

floyd算法和动态规划相关推荐

  1. Floyd算法的动态规划本质

    Floyd–Warshall(简称Floyd算法)是一种著名的解决任意两点间的最短路径(All Paris Shortest Paths,APSP)的算法.从表面上粗看,Floyd算法是一个非常简单的 ...

  2. 探求Floyd算法的动态规划本质

    Floyd–Warshall(简称Floyd算法)是一种著名的解决任意两点间的最短路径(All Paris Shortest Paths,APSP)的算法.从表面上粗看,Floyd算法是一个非常简单的 ...

  3. 动态规划 - Floyd算法求最短路径 - (Matlab建模)

    Floyd算法又称为弗洛伊德算法.插点法,是一种利用动态规划的思想寻找给定的加权图中多源点之间最短路径的算法,与Dijkstra算法类似.该算法名称以创始人之一.1978年图灵奖获得者.斯坦福大学计算 ...

  4. 算法设计(动态规划实验报告) 基于动态规划的背包问题、Warshall算法和Floyd算法

    一.名称 动态规划法应用 二.目的 1.掌握动态规划法的基本思想: 2.学会运用动态规划法解决实际设计应用中碰到的问题. 三.要求 1.基于动态规划法思想解决背包问题(递归或自底向上的实现均可): 2 ...

  5. 【动态规划】套汇问题(Floyd算法)

    套汇是指利用货币汇兑率的差异将一个单位的某种货币转换为大于一个单位的同种货币.例如,假定1 美元可以买0.7 英镑,1 英镑可以买9.5 法郎,且1 法郎可以买到0.16美元.通过货币兑换,一个商人可 ...

  6. 【图论专题】Floyd算法及其扩展应用

    Floyd的拓展应用: 任意两点最短路 传递闭包 找最小环 恰好经过k条边的最短路(倍增) 题目列表: 题目 算法 AcWing 1125. 牛的旅行 任意两点最短路Floyd AcWing 343. ...

  7. 图的单源最短路径,Floyd算法(数据结构c++)

    这个算法结构很是简单,但是理解还是有一定的困难,一开始做的时候想不明白,跟着算法自己动手画画就知道这个算法具体是怎么回事了. 时间复杂度是O(N*3) 算法有点动态规划的意思,有两个数组,一个(dis ...

  8. 最短路径—Dijkstra算法和Floyd算法

    Dijkstra算法 1.定义概览 Dijkstra(迪杰斯特拉)算法是典型的单源最短路径算法,用于计算一个节点到其他所有节点的最短路径.主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止.Di ...

  9. 短小精悍的多源最短路径算法—Floyd算法

    前言 在图论中,在寻路最短路径中除了Dijkstra算法以外,还有Floyd算法也是非常经典,然而两种算法还是有区别的,Floyd主要计算多源最短路径. 在单源正权值最短路径,我们会用Dijkstra ...

最新文章

  1. 如何设置minSdkVersion和targetSdkVersion
  2. Lvs+keepalived 高可用性负载均衡自动化配置
  3. html 分割线_零基础网页设计/前端/html,第四课:前三课总结,以及单标签img
  4. 安装 RAILS ANNOTATE_MODELS 插件.
  5. Maskros的蓝桥刷题之路(1-13)
  6. 【C语言进阶】 宏定义实现字符串引用
  7. microbit编程_使用图形化编程实现主控板与手机蓝牙通讯(2019.3.25)
  8. 一起玩Docker之1——Ubuntu配置安装Docker运行环境并安装(Ubuntu、Centos)镜像
  9. python画散点图-python学习之matplotlib绘制散点图实例
  10. 466.统计重复个数
  11. 2022年最新《谷粒学院开发教程》:6 - 整合SpringCloud
  12. 领峰:普通人如何炒白银技巧和方法有哪些
  13. MMORPG游戏优化报告
  14. Data Service相关概念
  15. python cv2什么意思_Python CV2的基本操作
  16. PHP7.2中AES加密解密方法mcrypt_module_open()替换方案
  17. sql 语句in 使用占位符
  18. UML时序图画法简介-sequenceDiagram
  19. 软件测试基础面试常问问题(一)
  20. 工业相机的传感器靶面大小

热门文章

  1. stl源码剖析_《STL源码剖析》学习笔记——空间配置器
  2. html5中加亮文本,html实现高亮关键字
  3. mysql中systimestamp_oracle数据库中timestamp是什么数据类型
  4. node爬取某app数据_某APP次日留存数据报告
  5. 大数据 清华 覃征_2021年清华(清华大学)大数据工程考研难度解析、考研经验分享...
  6. x86虚拟机NXVM_Centos6.5 x86_64系统安装kvm虚拟机—基础篇
  7. Tomcat9 无法启动组件[Connector[AJP/1.3-8009]]
  8. 【微信小程序】给绑定事件传参数
  9. RedHat7.0启动后黑屏
  10. Nutch开发(四)