动态规划所有点对的最短距离

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
• • • • • • • • FLOYD(int *L,int n) {int *D=(int *)malloc((n+1)*(n+1)*sizeof(int)); D L {将数组L复制到D}; for(k=0;k<n;k++) for(i=0;i<n;i++) for(j=0;j<n;j++) D[i*n+j]=min(D[i*n+j], D[i*n+k]+D[k*n+j]); }
//逐次将各点加入S // 在当前还未找到最短路径的顶点集中 选取具有最短距离的顶点u //标记顶点u已从集合T加入到集合S中 // 修改从 v0 到其他顶点的最短距离和最 短路径
• void Dijkstra ( int G[][N],int v0,int dist[], • int path[],int n)
② ③ ④
s: dist: path:
-1
1
0
1
10
01 50 1
1
30
0 60 90 3
1
4
4

第五步,将S外距离S 最近的点v5加入S。更新 相应信息。
② ③
⑤ ④
s: dist: path:
-1
1
0
1
10
1 50 1
1
30
01
60
1
4
3
• void Dijkstra ( int G[][N],int v0,int dist[], • int path[],int n) • //源点 v0 到其他顶点的最短距离 dist 和 最短路径下标path • { int *s=new int[n]; • int minDis, i, j, u; • //初始化三个数组 •
由于狄克斯特拉算法的时间复杂度是O(n2), 所以n次调用狄克斯特拉算法的时间复杂 度是O(n3)。
该问题具有最优子结构性质
例如上图中,若路线I和J是A到C的 最优路径,则根据最优化原理,路线J 必是从B到C的最优路线。
子问题的构造
• 原问题:每个顶点到其他所有顶点的最 短距离 • 最小的子问题D0:从顶点i (不得经过任 何其他顶点)到顶点j的距离; • 子问题D1:从顶点i(可以经过顶点1, 不得经过其他任何其他顶点)到顶点j的 距离。

初始状态下,S中只 有一个点(源点v1)。
S[i]为顶点i是否属于集合S
s: dist: path:
-1 1
0
0
10
0 ∞
0
30
0
100
dist[i]为源到顶点i的最短特殊路径长度 1 -1 1 1
path[i]为顶点i的最优前驱顶点

第二步,将S外距离S 最近的点v2加入S。更新 相应信息。
∞ 0 50 ∞ ∞
∞ ∞ 0 ∞ 10 ∞ ∞ 20 0 60 ∞∞ ∞∞ 0
Dijkstra算法的选择策略
开始时集合S中只有一个点,即源 用dist[i]存储源点到顶点i的距离 Dijkstra算法每次从S外选取距离源点 最近的顶点u,添加到S中,同时修改源点 到S外的点最短距离dist数组。一旦S包含 了所有V中顶点,dist就记录了从源到所有 其它顶点之间的最短路径长度。
dist[u]+G[u][j]<dist[j] )
• dist[j]=dist[u]+G[u][j]; • path[j]=u; • }}}
计算过程
• 例:考虑下图所示的带权有向图,求所 有顶点之间的最短距离。
1
2 8
2
1 9 6
(a)
1
0 2
9
V = 2
3
L= 8 0 6
1 ∞ 0
(b)
3
Di,jk:从顶点i(可以经过顶点1、顶点
2、……顶点k)到顶点j的距离。
1 D2[1][3]: 从顶点1到顶点3的距离(也可以经过顶点2) 0 2 9 0 2D [1][3]=9 9 1 ( 2: 仍是 ; 2 1)不经过顶点 1 9 8 D1 = D0 = 8 0 6 8 0 6 (2)过顶点2: D [1][2]+D [2][3]=2+6=8 2
子问题 Dk-1 :从顶点 i(可以经过顶点 1、顶点 如果从顶点 i:到子问题 到顶点 j从顶点 k走更近,则 从子问题 Dk-1 Dk,仅仅多考虑了 2 、 …… 、顶点 k-1 )到顶点 j 的距离。 k 一个顶点 k 。 i到j的距离di,j =i到k的距离di,kk-1 + k到j的距离dk,jk-1 子问题Dk:从顶点i(可以经过顶点 1、顶点 我们需要重新考虑从 i 到 j 的距离: 如果顶点 i到顶点 j从顶点 k走更远,甚至走不通, 2、……顶点 k-1、顶点 k)到顶点 j的距离。 k =d k-1 。 顶点i到顶点j,是不是从d ki,j 走会更近? 则保持原来的距离不变 i,j
4 单源最短路径
给定带权有向图G =(V,E),其中每条 边的权是非负实数。另外,还给定V中的 一个顶点,称为源。现在要计算从源到 所有其它各顶点的最短路长度。这里路 的长度是指路上各边权之和。这个问题 通常称为单源最短路径问题。
8.3 单源最短路径
例如,对右图中的有向 图,应用Dijkstra算法计算 从源顶点1到其它顶点间最 短路径。 0 10 ∞ 30 100 用邻接矩阵表 示如右图:
例如,对右图中 的有向图,应用 Dijkstra算法计算从 源顶点1到其它顶点 间最短路径的过程列 在下页的表中。
s:
1
1
1
1
1
distance: 由源点1到顶点 0 10 5的路径为: 50 30 601->4->3->5 path:
0 1 4 1 3
方法一:重复调用Dijkstra算法n次
• 可轮流以每一个顶点为源点,重复调用狄克斯 特拉算法函数 Dijkstra() n 次,即可求得所有顶 点之间的最短路径和最短距离。 • 利用 Dijkstra() 函数求所有顶点之间的最 短路径算法如下。其中,distance[i][j]中存放着 从顶点i到顶点j的最短距离,path[i][j]中存放着 从顶点i到顶点j的最短路径的前一顶点下标。
练习
• 有四种面值的硬币:1分 5 分 7分 11分, 要找钱15分,最少要找多少个硬币? • 用动态规划来解决
选做题
1、设A和B是两个字符串。我们要用最少的字符 操作将字符串A转换为字符串B。这里所说的字 符串操作包括: (1) 删除一个字符; (2) 插入一个字符; (3) 将一个字符改为另一个字符; 将字符串A变换为字符串B所用的最少字符操作成 为字符串A到字符串B的编辑距离,记为d(A,B)。 试设计一个有效算法,对任给的两个字符串A和 B,求他们的编辑距离d(A,B) A=“abcde”,B=“acdefa”
算法设计
重要发现:在从Dk-1到Dk的计算过程中中, 第k行和第k列是不变的。(因为说从顶点k到顶点j
或顶点j到顶点k允许经过顶点k是没有意义的)
而在从Dk-1到Dk的计算过程中也只用 到第k行和第k列,也就是说,在这一步 的计算过程中用到的数据都不会被覆盖。 故在算法中仅使用一个矩阵D即可
FLOYD算法
• •
• • • •
//从源点v0到其他顶点的最短距离dist和最 短路径下标path {int *s=new int[n];
int minDis , i, j, u; //初始化三个数组 for(i=0;i<n;i++) {
• dist[i]=G[v0][i];
• s[i]=0; • if(I != v0 && dist[i]<MAX) path[i]=v0;
• 子问题Dk:从顶点i(可以经过顶点1、 顶点2、……顶点k,不得经过任何其他 顶点)到顶点j的距离。 • 子问题Dn:从顶点i(可以经过顶点1、 顶点2、……顶点n )到顶点j的距离。 ——即原问题
递推关系的建立
• 由di,jk-1推出di,jk的过程如下 若k=0, k的过程,主要考虑的是顶点k 由di,jk-1 推出 d i,j di,jk=L[i][j] (因为从i到j不允许经过任何其他顶点) 的加入会引起什么变化?由不允许路过顶点 若 1≤k ≤ n, k到允许路过顶点 k,有些点间的距离是否会 di,jk=min{di,jk-1 , di,kk-1 +dk,jk-1} 变的更近。
取最小值8
6
3
1
1
1 ∞ 0
1 3
0
0 2 8 0 2 38 D1[3][2]:从顶点 到顶点2的距离(可以经过顶点 1) D [2][3]: 从顶点 2 到顶点 3 的距离(可以经过顶点 1) 在 D1 中,第 1 行和第一列是不变的,因为 1 (D 1)不经过顶点 1: 仍是D0 [3][2]= ∞; D = 7 0 6 = 3 8 0 6 ( 1 )不经过顶点 1 : 仍是 D [2][3]=6 ; 2 说从顶点1到顶点j或顶点0 j到顶点1:允许经 ( 2)过顶点 :0 D0[3][1]+D0[1][2]=1+2=3 1 3 0 过顶点 1是没有意义的 1 1 3 (2)过顶点 1: D0[2][1]+D0[1][3]=8+9=17 取最小值3 取最小值6
• 算法中,我们不断更新以下三个数组: • s数组: s[i],当顶点i加入S时,s[i]置1 • Distance数组: Distance[i]记录原点到 顶点i的最 短特殊路径长度。 • path数组: path[i]记录顶点i在其最短特殊路径 上的前驱顶点。由该数组可求得原点到各点的 最短路径。如:设源点是顶点1, path数组如下
• else path[i]=-1;
• } • s[v0]=1;//标记顶点v0已从集合T加入到集合S中 • // 在当前还未找到最短路径的顶点集中选取具有最短距 离的顶点u • for(i=1;i<n;i++) • {minDis=MAX; • for(j=0;j<=n;j++)
• if(s[j]==0&&dist[j]<minDis)

s: dist: path:
-1
1
0
01
10
0 ∞ 60
0
30
0
100
1
-1 2 1
1

第三步,将S外距离S 最近的点v4加入S。更新 相应信息。
② ④
s: dist: path:
-1
1
0
1
10
0 60 50 41
01
30
0
100 90
1
2
1
4

第四步,将S外距离S 最近的点v3加入S。更新 相应信息。
• voidShortPath(AdjMWGraph &G, **distance, int **path) • { • Int n=G.NumOfVertices(); • for(inti=0;i<n;i++) • Dijkstra(G,i,distance[i],path[i]); • }
int
第 七 章 动 态 规 划
7.5所有点对的最短路径问题
• 对于一个各边权值均大于0的有n个顶点 的带权有向图G=(V,E),求所有顶点之间 的最短路径和最短距离。
图的邻接矩阵表示法
1
源自文库
1
0 2
9
2
2
8 9 6
1
3
V = 2
3
L= 8 0 6
1 ∞ 0
(b)
(a)
复习Dijkstra算法
其基本思想是,设置顶点集合S并不断地作 贪心选择来扩充这个集合。一个顶点属于集合S 当且仅当从源到该顶点的最短路径长度已知。 初始时,S中仅含有源点。设u是G的某一个 顶点,把从源点到u且中间只经过S中顶点的路称 为从源到u的特殊路径,并用数组distance记录 当前每个顶点所对应的最短特殊路径长度。 Dijkstra算法每次从V-S中取出具有最短特殊路 长度的顶点u,将u添加到S中,同时对数组 distance作必要的修改。一旦S包含了所有V中顶 点,distance就记录了从源到所有其它顶点之间 的最短路径长度。
8.3 单源最短路径
Dijkstra算法的迭代过程: 迭代 初始 1 2 3 4 S {1} {1,2} {1,2,4} {1,2,4,3} {1,2,4,3,5} u 2 4 3 5 dist[2] dist[3] dist[4] dist[5] 10 10 10 10 10 maxint 60 50 50 50 30 30 30 30 30 100 100 90 60 60
• {u=j; • minDis=dist[j];
u到j有边相连,j 才有可能因u的加 • } 入而距离源点更 近 • s[u]=1;//标记顶点u已从集合T加入到集合 S中
• //修改从v0到其他顶点的最短距离和最短路径 • for(j=0;j<n;j++)


if( s[j]==0&&G[u][j]<MAX&&
相关文档
最新文档