題目內容:
現在有乙個 m * n 的整數矩陣,請你編寫乙個程式計算出一條從左到右穿過矩陣的路徑,並使此路徑的費用最小。路徑從矩陣的左側的第一列的任意單元格開始,逐步穿過矩陣到達最右側的一列的任意單元格。每一步是指從某單元格進入它一列的相鄰單元格(如下圖,可以是橫向或斜向)。矩陣的第一行和最後一行實際是相鄰的,你可以想象矩陣是包裹在乙個橫放的圓柱體外面(這點很重要)。
路徑的花費是指這條路徑所穿越的所有單元格中的數字之和。
輸入描述
輸入包括一系列矩陣描述。每個矩陣描述的第一行是 m 和 n,即矩陣的行數和列數;之後的 m 行,每行包括 n 個以空格分開的整數,則是當前矩陣的值,注意矩陣的值未必是正數。
矩陣的行數 m 和列數 n 的範圍是:1 <=m<=10、 1<=n<=100;所有路徑的費用值都可以用 30bit 的整數表示。
輸出描述
針對每乙個矩陣,找出費用最小的路徑,並將其輸出。每個矩陣的輸出包括兩行,第一行是路徑本身,即輸出每一步所在的行,第二行則是該路徑的費用。
如果對於同乙個矩陣有多條不同的費用最小路徑,則輸出左端行號較小的一條。
輸入樣例
5 63 4 1 2 8 6
6 1 8 2 7 4
5 9 3 9 9 5
8 4 1 3 2 6
3 7 2 1 2 3
輸出樣例
1 2 1 5 4 5
1.關於為什麼要從最右邊找到最左邊
如果從左邊找到右邊,因為你不知道後面的哪乙個加到最後之後會最小,萬一當前選的最小的加到最後並不是最小的呢?如果從最右邊倒著找,你每次找的最小的可以往前推出一整組最小的。
2.關於選擇乙個點的右上、右、右下的問題(越界)
右上:橫座標i+1、縱座標(j+1) % n
右:橫座標i+1、縱座標j
右下:橫座標i+1、(j-1+n) % n
dp[j][i] += min(min(dp[j][i + 1], dp[(j + 1) % n][i + 1]), dp[(j - 1 + n) % n][i + 1]);
3.關於如何儲存路徑的問題
當求出總路程最小的min時,記錄其所在行,從該行起,往後找,題目資料第乙個點是(0,0),從(0,0)開始找右上(4, 1)、右(0, 1)、右下(1,1).
有乙個關係可以確定右上、右、右下哪個點在是我們確定的最小min的路線中
dp[i][j] - a[i][j] == dp[(i + q[k] + n) % n][j + 1]
如果找到該點,則再從該點找右上、右、右下,重複此步驟知道找到最後一列。
ac**
#include using namespace std;
int a[11][101] = , dp[11][101] = ;
int path[11] = ;//記錄最後結果路徑
int q[3] = ;
int min(int a, int b)
int main()
int min = dp[0][0];
int pos = 0;
for (int i = 1; i < n; i++)
if (min > dp[i][0])
//找到最小的min路線耗費
path[0] = pos + 1;
for (int j = 0; j < m; j++)
}int i = 0;
for (i = 0; i < n; i++)
cout << path[i] << " ";
cout << path[i] << endl;
cout << min << endl;
} return 0;
}
矩陣連乘(動態規劃)
題目描述 給定n個矩陣 a1,a2,an 其中ai與ai 1是可乘的,i 1,2 n 1。如何確定計算矩陣連乘積的計算次序,使得依此次序計算矩陣連乘積需要的數乘次數最少。例如 a1 a2 a3 a4 a5 a6 最後的結果為 a1 a2a3 a4a5 a6 最小的乘次為15125。思路 動態規劃演算...
動態規劃 矩陣連乘
includeusing namespace std 無論括號怎麼分這些連續相乘的矩陣,最後括號都可以歸結到只有兩對括號,把整個連乘的矩陣分成兩部分 0 i j m i j min i 遞迴計算矩陣連乘 int liancheng int i,int j,int p,int s return min...
動態規劃 矩陣連乘
動態規劃常常用來解決,具有最優子結構,重疊子問題的物件。最優子結構 即通過分析問題,將問題分解為多個子問題。然後每個子問題繼續分解為更多子問題。從底往上求出最有值,由最優值確定最優解。重疊子問題 在計算過程中不同子問題可能都會計算某個值。若每個子問題都去求解同乙個值,浪費時間。動態規規劃對每乙個子問...