多段圖的最短路徑問題
問題:設圖G=(V,E)是一個帶權有向圖,如果把頂點集合V划分成k個互不相交的子集Vi(2<=k<=n,1<=i<=k),
使得E中的任何一條邊<u,v>,必有u∈Vi, v∈Vi+m(1<=i<k,1<i+m<=k),則稱圖G為多段圖,稱s∈V1為源點,
t∈Vk為終點。
多段圖的最短路徑問題為從源點到終點的最小代價路徑。
子問題:設Cuv表示多段圖的有向邊<u,v>上的權值,將從源點s到終點t的最短路徑長度即為d(s,t),
考慮原問題的部分解d(s,v),顯然有下式成立
d(s,v)=Csu (<s,v>∈E)
d(s,v)=min(d(s,u)+Cuv) (<u,v>∈E)
算法:多段圖的最短路徑問題
輸入:多段圖的代價矩陣
輸出:最短長度及路徑c[n][n]
1.循環變量j從1~n-1重復下述操作,執行填表工作
1.1考察頂點j的所有入邊,對於邊<i,j>∈E,執行下述操作
1.1.1cost[j]=min{cost[i]+c[i][j]};
1.1.2path[j]=使cost[i]+c[i][j]最小的i;
1.2 j++;
2.輸出最短路徑長度cost[n-1];
3.循環變量i=path[n-1].循環直到path[i]=0,輸出最短路徑經過的頂點;
3.1 輸出path[i];
3.2 i=path[i]
#include<iostream> #include<algorithm> #include<stdio.h> #define Max 0xffff using namespace std; //動態規划求最短路徑 void dp_path(int c[][100], int *cost, int *path) { int m, n; cout << "輸入頂點個數和邊個數" << endl; cin >> n >> m; //初始化代價矩陣 for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) c[i][j] = Max; //輸入代價矩陣 int u, v, s; for (int i = 0; i < m; i++) { cin >> u >> v >> s; //cout<<u<<v<<s<<endl; c[u][v] = s; } for(int i=0;i<n;i++) cost[i]=Max; path[0] = -1; cost[0] = 0; for (int j = 1; j < n; j++) { for (int i = j-1; i >=0; i--) { if (cost[j] > cost[i] + c[i][j]) { path[j] = i; cost[j] = cost[i] + c[i][j]; } } } cout<<cost[n-1]<<endl; int i=path[n-1]; cout<<path[n-1]<<endl; while(path[i]>=0){ cout<<path[i]<<endl; i=path[i]; } } int main() { int c[100][100], cost[100], path[100]; dp_path(c, cost, path); getchar(); return 0; }