1. 程式人生 > >牛刀小試一:矩陣最短路徑

牛刀小試一:矩陣最短路徑

題目:

給定一個M×N的矩陣,定義一條路徑為:從矩陣左上頂點數字出發到達右下數字,每一次只可以從一個數字出發向右移動一步或向下移動一步,定義路徑和為:路徑經過的數字的和。要求編寫一個程式,找到路徑和最小的那條路徑,並給出最小路徑和。

給定如圖所示矩陣:一條路徑為2->0->3->6->9->5,路徑和為25

[2 ,0 ,11,1 ]

[4 ,3 ,6 ,12]

[7 ,10,9 ,5 ]

要求:測試時輸入一個矩陣(輸入方式隨意),然後程式輸出該矩陣的最小路徑和與路徑。

思路:動態規劃求解。dp[i][j]表示從點D[0][0]到點D[i][j]的最短路徑和。
對於點D[i][j]它只能從點D[i-1][j]或者點D[i][j-1]而來,所以有遞推公式dp[i][j] = min(dp[i-1][j],dp[i][j-1]) + D[i][j]; 特殊的,對於第一行的點D[0][j]只可能由點D[0][j-1]而來;對於第一列的點D[i][0]只可能由點D[i-1][0]而來。

程式碼解答:

#include<iostream>
using namespace std;
const int maxn = 1001;                      //行列最大值
int M,N,K=0;                                //M行N列,路徑有K個結點
int D[maxn][maxn];                          //儲存原始矩陣值
int dp[maxn][maxn];                         //從D[0][0]到D[i][j]路徑最小值
int mp[maxn];                               //儲存路徑中的結點值
int main(){
    cin >> M >> N;
    for(int i=0; i<M; i++)
        for(int j=0; j<N; j++)
            cin >> D[i][j];
    dp[0][0]=D[0][0];
    for(int i=1; i<M; i++)
        dp[i][0] = dp[i-1][0]+ D[i][0];     //對於第一列的點D[i][0],只可能是從上面的點D[i-1][0]往下走
    for(int j=1; j<N; j++)
        dp[0][j] = dp[0][j-1]+ D[0][j];     //對於第一行的點D[0][j],只可能是從左邊的點D[0][j-1]往右走
    for(int i=1; i<M; i++)
        for(int j=1; j<N; j++)              //點D[i][j],是從D[i][j-1]和D[i-1][j]較小的而來
            dp[i][j] = min(dp[i-1][j],dp[i][j-1]) + D[i][j];
    int i=M-1,j=N-1;
    mp[K++]=D[i][j];
    while(i>=0 && j>=0){                    //倒著找路徑上的點
        if(i==0 && j==0){
            break;
        } else if(i==0){                    //在第一行上,那麼上一個點只能是左邊的點
            mp[K++]=D[i][j-1];
            j--;
        } else if(j==0){                    //在第一列上,那麼上一個點只能是上面的點
            mp[K++]=D[i-1][j];
            i--;
        } else {                            //否則就找左邊和上面的dp最小對應的那個點D
            if(dp[i-1][j]<dp[i][j-1]){
                mp[K++]=D[i-1][j];
                i--;
            } else {
                mp[K++]=D[i][j-1];
                j--;
            }
        }
    }
    for(int i=K-1;i>=0;i--){
        cout<<mp[i];
        if(i!=0) cout<<"->";
    }
    cout << endl << dp[M-1][N-1] <<endl;
    return 0;
}


//測試
3 5
1 2 3 4 5
6 7 8 9 10
11 12 13 14 15
//輸出
1->2->3->4->5->10->15
40

相關推薦

牛刀小試矩陣路徑

題目: 給定一個M×N的矩陣,定義一條路徑為:從矩陣左上頂點數字出發到達右下數字,每一次只可以從一個數字出發向右移動一步或向下移動一步,定義路徑和為:路徑經過的數字的和。要求編寫一個程式,找到路徑和最小的那條路徑,並給出最小路徑和。 給定如圖所示矩陣:一條路徑為2->

演算法學習——動態規劃 例題矩陣路徑(java)

給定一個矩陣m,從左上角開始每次只能向右或者向下走,最後到達右下角的位置, 路徑上所有的數字累加起來就是路徑的和,返回所有的路徑中的最小的路徑的和。 如果給定的m如大家看到的樣子,路徑1,3,1,0,6,1,0是所有路徑中路徑和最小的,所以返回12. 1 3 5 9 8 1 3 4 5 0 6 1

資料結構篇校園路徑導航(地圖資料的配置以及圖的建立)

首先去找一張學校的地圖,並且自己配置好資料和路線 在程式碼裡面寫好資料 //地點資訊 char _mapName[32][50] = {"行政樓","實驗樓D", "教學樓A", "籃球場", "足球場", "A4", "實驗樓C", "教學樓B", "A2", "A6", "計

NYOJ街區路徑問題(曼哈頓距離)

描述 一個街區有很多住戶,街區的街道只能為東西、南北兩種方向。 住戶只可以沿著街道行走。 各個街道之間的間隔相等。 用(x,y)來表示住戶坐在的街區。 例如(4,20),表示使用者在東西方向第4個街道,南北方向第20個街道。 現在要建一個郵局,使得各個住戶到郵局的距離之和最少。 求現在這個郵

OJ 1006街區路徑問題

OJ 1006:街區最短路徑問題 因為只能東西,南北走,所以求一點到另一點的距離就等於橫縱座標的差的絕對值之和,我們將每個點的橫座標取出來,縱座標取出來,這個問題就成了這些數到哪個數的距離的和最小,分別求出橫座標和縱座標對應的哪個和,然後求和就行了 n=int(input()) wh

BZOJ4016[FJOI2014]路徑樹問題

技術分享 push_back algo 最短路徑 += ostream %d 路徑 題目 淺談樹分治:https://www.cnblogs.com/AKMer/p/10014803.html 題目傳送門:https://www.lydsy.com/JudgeOnline/

資料結構篇校園路徑導航(三地圖影象顯示以及完整程式)

首先是地圖的顯示,因為控制檯限制,只能通過外部程式來顯示圖片 如果你使用的是VC6.0或者Dev C++將準備好的圖片放在工程根目錄,命名為SchoolMap.png 如果有小夥伴和我一樣使用的是CLion的話,就把圖片放到cmake-build-debug下面 ) 在ma

資料結構篇校園路徑導航(二弗洛伊德演算法理解與應用)

求最短路徑最常用的有迪傑斯特拉(Dijkstra)和弗洛伊德(Floyd)演算法兩種。本著簡潔為王道的信條,我選擇了Floyd演算法。 Floyd演算法 首先來看一個簡單圖,紅色標記代表在陣列的下標,橙色標記代表距離(邊權值) 我們用D[6][6]這個矩陣儲存兩點之間最短路徑,

矩陣路徑

程式設計師面試指南中的一個題目:         給定一個矩陣m,從左上角開始每次只能向右或向下走,最後達到右下角的位置,路徑上所有數字的累加和就是路徑和,求所有路徑中的最小路徑和。         根據動態規劃實現,構建矩陣dp,dp[i][j]為從左上角(0,0)到(i

動態規劃3矩陣路徑和問題

題目:有一個矩陣map,它每個格子有一個權值。從左上角的格子開始每次只能向右或者向下走,最後到達右下角的位置,路徑上所有的數字累加起來就是路徑和,返回所有的路徑中最小的路徑和。 給定一個矩陣map及它的行數n和列數m,請返回最小路徑和。保證行列數均小於等於100. 測試樣例

hihocoder1081 路徑·

http://hihocoder.com/problemset/problem/1081 描述 萬聖節的早上,小Hi和小Ho在經歷了一個小時的爭論後,終於決定了如何度過這樣有意義的一天——他們決定去闖鬼屋! 在鬼屋門口排上了若干小時的隊伍之後,剛剛進入鬼屋的小Hi和小Ho都頗飢餓,於

路徑(二)—Dijkstra演算法(通過邊實現鬆弛鄰接矩陣

上一節通過Floyd-Warshall演算法寫了多源節點最短路徑問題: 這一節來學習指定一個點(源點)到其餘各個頂點的最短路徑。也叫做“單源最短路徑”Dijkstra。 例如求下圖中1號頂點到2、3、4、5、6號頂點的最短路徑。 用二維陣列e儲存頂點之間邊的關係,初

經典演算法之圖的路徑()Dijkstra演算法

Dijkstra演算法可以說基本上每一本有講到圖的最短路徑的書上都會有的一個演算法,但基本上都是講原理和虛擬碼,今天自己用Java程式碼給實現了一下,記錄在此。 Dijkstra演算法只是解決某些圖的最短路徑問題,這些圖需要滿足以下條件:權值非負、有向圖。並且該演算法只適用

本通網站 1378路徑(shopth)

gif sso 路徑 oier 連通 con () algo 如果 【題目描述】 給出一個有向圖G=(V, E),和一個源點v0∈V,請寫一個程序輸出v0和圖G中其它頂點的最短路徑。只要所有的有向環權值和都是正的,我們就允許圖的邊有負值。頂點的標號從1到n(n為

兩點之間路徑弗洛伊德算法

int code 指定 matrix ++ 計算 之間 logs 執行函數 弗洛伊德算法是計算無向有權圖中兩點間最短路徑的算法,復雜度為O(n^3)。其思路是將兩點間距離分為過(指定的)第三點或是不過,然後取它們的最小值,如此循環就可以得到兩點之間真正的最小值。 void

【算法】Dijkstra算法(單源路徑問題) 鄰接矩陣和鄰接表實現

當前 prior 排序 發的 單源最短路徑 fine emp eat col Dijkstra算法可使用的前提:不存在負圈。 負圈:負圈又稱負環,就是說一個全部由負權的邊組成的環,這樣的話不存在最短路,因為每在環中轉一圈路徑總長就會邊小。 算法描述:   1.找到最

路徑算法 ()——求出路徑長度 (*^__^*) 嘻嘻……

沒有 str -1 man 最大 連線 問題 輸入 sha 【問題描述】: 平面上有n(n<=100)個點,每個點的坐標均在-10000~10000之間。 其中的一些點之間有連線。若有連線,則表示可以從一個點到

筆記路徑算法—Dijkstra(迪傑斯特拉)

意思 最終 else min out 拓展 clas stream 便是 文中代碼下如下: #include<iostream> #include<cstdio> #include<fstream> #include<algor

圖論(三) () 路徑算法 1.Floyed-Warshall算法

路徑 最短路徑 一行 AS 個數 math stream 並且 -s 這幾周開始正式系統學習圖論,新學期開始新的記錄。由於二模和生物地理兩門高考的臨近,時間比較倉促,所以暫時跳過圖論的(一)和(二),即圖的儲存和遍歷。從最短路徑算法學起,首先要學習的是Floyed-Wars

圖論(三) ()路徑算法 2.Dijkstra算法

set print turn 重復 跳過 int 算法導論 出發 AS Dijkstra 算法解決的是帶權重的有向圖上單源最短路徑問題,該算法要求所有邊的權重都為非負值。該算法的時間復雜度是O(N2),相比於處理無負權的圖時,比Bellmad-Ford算法效率更高。 算法描