1. 程式人生 > >CH5103 傳紙條【線性dp】

CH5103 傳紙條【線性dp】

約定 stdio.h algorithm style scan space 題意 main 矩陣

5103 傳紙條 0x50「動態規劃」例題

描述

給定一個 N*M 的矩陣A,每個格子中有一個整數。現在需要找到兩條從左上角 (1,1) 到右下角 (N,M) 的路徑,路徑上的每一步只能向右或向下走。路徑經過的格子中的數會被取走。兩條路徑不能經過同一個格子。求取得的數之和最大是多少。N,M≤50。

輸入格式

第一行有2個用空格隔開的整數n和m,表示有n行m列(1<=n,m<=50)。
接下來的n行是一個n*m的矩陣,每行的n個整數之間用空格隔開。

輸出格式

一個整數,表示答案。

樣例輸入

3 3
0 3 9
2 8 5
5 7 0

樣例輸出

34

數據範圍與約定

  • 30%的數據滿足:1<=m,n<=10
    100%的數據滿足:1<=m,n<=50

來源

CCF NOIP2008 T3

題意:n*m的格子裏每個格子有一個權值,從(1,1)走到(n,m)兩條路,(只能向下或者向右)求路徑之和。走過的格子只算一次權值。

思路:

把“路徑長度”即當前走過的步數作為DP的“階段”。【因為只能向下或向右,走到(n,m)時的路徑長度是n+m-2】

每一個階段中,把兩條路徑同時擴展一步,路徑長度增加1,從而轉移到下一個階段。

還需確定兩條路徑當前的末尾位置。並且 x1+y1 = x2 + y2 = i + 2

所以就可以用三維dp維護,每次有4種擴展方式。並且要考慮擴展後是否兩個點坐標相同。

目標是dp[n+m-2][n][n]

 1 #include <bits/stdc++.h>
 2
#include<iostream> 3 #include<cmath> 4 #include<algorithm> 5 #include<stdio.h> 6 #include<cstring> 7 #include<map> 8 9 #define inf 0x3f3f3f3f 10 using namespace std; 11 typedef long long LL; 12 13 int n, m; 14 const int maxn = 55; 15 int g[maxn][maxn]; 16 int
dp[maxn * 2][maxn][maxn] = {0}; 17 18 int main() 19 { 20 scanf("%d%d", &n, &m); 21 for(int i = 1; i <= n; i++){ 22 for(int j = 1; j <= m; j++){ 23 scanf("%d", &g[i][j]); 24 } 25 } 26 27 dp[0][1][1] = g[1][1]; 28 for(int i = 0; i <= n + m - 2; i++){ 29 for(int x1 = 1; x1 <= min(n, i + 1); x1++){ 30 for(int x2 = 1; x2 <= min(n, i + 1); x2++){ 31 int y1 = i + 2 - x1, y2 = i + 2 - x2; 32 if(x1 == x2 && y1 == y2){ 33 dp[i + 1][x1][x2] = max(dp[i + 1][x1][x2], dp[i][x1][x2] + g[x1][y1 + 1]); 34 dp[i + 1][x1 + 1][x2 + 1] = max(dp[i + 1][x1 + 1][x2 + 1], dp[i][x1][x2] + g[x1 + 1][y1]); 35 } 36 else{ 37 dp[i + 1][x1][x2] = max(dp[i + 1][x1][x2], dp[i][x1][x2] + g[x1][y1 + 1] + g[x2][y2 + 1]); 38 dp[i + 1][x1 + 1][x2 + 1] = max(dp[i + 1][x1 + 1][x2 + 1], dp[i][x1][x2] + g[x1 + 1][y1] + g[x2 + 1][y2]); 39 } 40 41 if(x1 == x2 + 1 && y1 + 1 == y2){ 42 dp[i + 1][x1][x2 + 1] = max(dp[i + 1][x1][x2 + 1], dp[i][x1][x2] + g[x1][y1 + 1]); 43 } 44 else{ 45 dp[i + 1][x1][x2 + 1] = max(dp[i + 1][x1][x2 + 1], dp[i][x1][x2] + g[x1][y1 + 1] + g[x2 + 1][y2]); 46 } 47 48 if(x1 + 1 == x2 && y1 == y2 + 1){ 49 dp[i + 1][x1 + 1][x2] = max(dp[i + 1][x1 + 1][x2], dp[i][x1][x2] + g[x1 + 1][y1]); 50 } 51 else{ 52 dp[i + 1][x1 + 1][x2] = max(dp[i + 1][x1 + 1][x2], dp[i][x1][x2] + g[x1 + 1][y1] + g[x2][y2 + 1]); 53 } 54 } 55 } 56 } 57 printf("%d\n", dp[n + m - 2][n][n]); 58 return 0; 59 }

CH5103 傳紙條【線性dp】