題目連結:http://codeforces.com/problemset/problem/429/B
題意:
給你一個n*m的網格,每個格子上有一個數字a[i][j]。
一個人從左上角走到右下角,一個人從左下角走到右上角,要求兩條路徑有且僅有一個交點。
問你除去交點格子上的數字,路徑上數字之和最大是多少。
題解:
表示狀態:
dp[i][j][0/1/2/3] = max sum
表示從某個角走到(i,j)這個格子,最大路徑上數字之和
0,1,2,3分別代表左上角、右上角、左下角、右下角
找出答案:
路徑相交共有兩種方式:
列舉交點(i,j)。
ans = max dp[i-1][j][0] + dp[i+1][j][3] + dp[i][j-1][2] + dp[i][j+1][1]
ans = max dp[i-1][j][1] + dp[i+1][j][2] + dp[i][j-1][0] + dp[i][j+1][3]
如何轉移:
四種情況分別算:
(1)dp[i][j][0] = max dp[i-1][j][0]+a[i][j]
dp[i][j][0] = max dp[i][j-1][0]+a[i][j]
(2)dp[i][j][1] = max dp[i-1][j][1]+a[i][j]
dp[i][j][1] = max dp[i][j+1][1]+a[i][j]
(3)dp[i][j][2] = max dp[i+1][j][2]+a[i][j]
dp[i][j][2] = max dp[i][j-1][2]+a[i][j]
(4)dp[i][j][3] = max dp[i+1][j][3]+a[i][j]
dp[i][j][3] = max dp[i][j+1][3]+a[i][j]
邊界條件:
set dp = 0
AC Code:
1 #include <iostream> 2 #include <stdio.h> 3 #include <string.h> 4 #define MAX_N 1005 5 6 using namespace std; 7 8 int n,m; 9 int a[MAX_N][MAX_N]; 10 int dp[MAX_N][MAX_N][4]; 11 12 void read() 13 { 14 cin>>n>>m; 15 for(int i=1;i<=n;i++) 16 { 17 for(int j=1;j<=m;j++) 18 { 19 cin>>a[i][j]; 20 } 21 } 22 } 23 24 void work() 25 { 26 memset(dp,0,sizeof(dp)); 27 for(int i=1;i<=n;i++) 28 { 29 for(int j=1;j<=m;j++) 30 { 31 dp[i][j][0]=max(dp[i][j][0],dp[i-1][j][0]+a[i][j]); 32 dp[i][j][0]=max(dp[i][j][0],dp[i][j-1][0]+a[i][j]); 33 } 34 } 35 for(int i=1;i<=n;i++) 36 { 37 for(int j=m;j>=1;j--) 38 { 39 dp[i][j][1]=max(dp[i][j][1],dp[i-1][j][1]+a[i][j]); 40 dp[i][j][1]=max(dp[i][j][1],dp[i][j+1][1]+a[i][j]); 41 } 42 } 43 for(int i=n;i>=1;i--) 44 { 45 for(int j=1;j<=m;j++) 46 { 47 dp[i][j][2]=max(dp[i][j][2],dp[i+1][j][2]+a[i][j]); 48 dp[i][j][2]=max(dp[i][j][2],dp[i][j-1][2]+a[i][j]); 49 } 50 } 51 for(int i=n;i>=1;i--) 52 { 53 for(int j=m;j>=1;j--) 54 { 55 dp[i][j][3]=max(dp[i][j][3],dp[i+1][j][3]+a[i][j]); 56 dp[i][j][3]=max(dp[i][j][3],dp[i][j+1][3]+a[i][j]); 57 } 58 } 59 int ans=0; 60 for(int i=2;i<n;i++) 61 { 62 for(int j=2;j<m;j++) 63 { 64 ans=max(ans,dp[i-1][j][0]+dp[i+1][j][3]+dp[i][j-1][2]+dp[i][j+1][1]); 65 ans=max(ans,dp[i-1][j][1]+dp[i+1][j][2]+dp[i][j-1][0]+dp[i][j+1][3]); 66 } 67 } 68 cout<<ans<<endl; 69 } 70 71 int main() 72 { 73 read(); 74 work(); 75 }