61計蒜客 動態規劃基礎 蒜頭君的城堡之旅
阿新 • • 發佈:2018-03-01
部分 pos include 路徑 entry 一個 空格 如果 size
蒜國地域是一個 n 行 m 列的矩陣,下標均從 1 開始。蒜國有個美麗的城堡,在坐標 (n,m) 上,蒜頭君在坐標 (1,1) 的位置上。蒜頭君打算出發去城堡遊玩,遊玩結束後返回到起點。在出發去城堡的路上,蒜頭君只會選擇往下或者往右走,而在返回的路上,蒜頭君只會選擇往上或者往左走,每次只能走一格。已知每個格子上都有一定數量的蒜味可樂,每個格子至多經過一次。
現在蒜頭君請你來幫他計算一下,如何計劃來回行程,可以收集到最多的蒜味可樂。
輸出一行,輸出一個整數,表示蒜頭君在來回路上能收集到的蒜味可樂的最大值。
輸入格式
第一行輸入兩個整數 n,m(1≤n,m≤50),表示蒜國是一個 n 行 m 列的矩陣。 接下來輸入 n 行,每行輸入 m 個整數,代表一個 n×m 的矩陣,每個整數代表對應位置上的蒜味可樂數量,每行的每兩個整數之間用一個空格隔開。其中蒜頭君的位置和城堡的位置上沒有蒜味可樂,用 0 表示,其余位置上的整數範圍在 [1,100] 內。輸出格式
樣例輸入
3 3 0 2 9 4 8 6 2 7 0樣例輸出
36分析:
(可以理解為從起點出發的不相交的兩條路徑) 首先,要註意一個問題:不能先算出去的最大值,再算返回的最大值。這樣可能導致只保證了去的最大值,但沒有保證來回之和的最大值。也就是說,來回的優先級是相同的,但是如果先算去路的最大值就會使得去的優先級高於回的優先級。 容易註意到本題的範圍不大,所以可以用一個四維數組: f[i][j][k][l] 來表示路徑1走到 [i][j] 和路徑2走到 [k][l] 的和的最優值。 其中,因為走的步數相同,所以 i+j=k+l (可以利用這個等式來把空間和時間復雜度降一級),不難想到只要當前一步的兩條路徑沒有走到用一個點,兩條路徑就不會相交(如果相交,重疊部分的可樂只能領取一次,就不是最優情況)。 最後就不難寫出動規方程: f[i][j][k][l] = max(max(f[i-1][j][k-1][l], f[i][j-1][k-1][l]), max(f[i-1][j][k][l-1], f[i][j-1][k][l-1]))+map[i][j]+map[k][l]; 其中第一部分是求兩個路徑當前點的兩個前趨情況的和的最大值(一共是 2×2 四種情況,所以用了一個 max 套兩個 max)。 最最後,因為兩條路徑在終點還是會交於一點,所以千萬不能輸出 f[n][m][n][m] ,應該輸出 f[n-1][m][n][m-1] 。標程:
1 #include <iostream> 2 #include <cstdlib> 3 #include <cstring> 4 using namespace std; 5 int n,m,map[55][55],f[55][55][55][55]; 6 int main() 7 { 8 memset(f,0,sizeof(f)); 9 cin >> n >> m; 10 for (int i=1; i<=n; i++) 11 { 12 for (int j=1; j<=m; j++) 13 { 14 cin >> map[i][j]; 15 } 16 } 17 for (int i=1; i<=n; i++) 18 { 19 for (int j=1; j<=m; j++) 20 { 21 for (int k=1; k<=n; k++) 22 { 23 for (int l=1; l<=m; l++) 24 { 25 if (i+j!=k+l) 26 continue; 27 if (i==k && j==l) 28 continue; 29 f[i][j][k][l] = max(max(f[i-1][j][k-1][l], f[i][j-1][k-1][l]), max(f[i-1][j][k][l-1], f[i][j-1][k][l-1])) 30 +map[i][j]+map[k][l]; 31 } 32 } 33 } 34 } 35 cout << f[n-1][m][n][m-1] << endl; 36 return 0; 37 }
61計蒜客 動態規劃基礎 蒜頭君的城堡之旅