動態規划作業-多段圖的最短路徑問題


多段圖的最短路徑問題

問題:設圖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;
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM