1. 程式人生 > >Working out(DP)

Working out(DP)

return splay bsp clu http style 只有一個 out gif

題目描述:

技術分享圖片技術分享圖片技術分享圖片

題意:

有n*m個格子, 走過一個格子可以得到相應的分數.
A 從(1,1)沿 下 或 右 走到(n,m)
B 從(n,1)沿 上 或 右 走到(1,m)
兩人路徑有且只能有一個格子重合(重合格子的分數不算), 求兩人分數之和的最大值.

首先要保證只有一個格子重合,那麽只可能是以下兩種情況:
1) A向右走,相遇後繼續向右走,而B向上走,相遇後繼續向上走
2) A向下走,相遇後繼續向下走,而B向右走,相遇後繼續向右走

接著枚舉相遇的格子(i,j)即可,考慮四個方向的dp

dp1[i][j] := 從 (1, 1) 到 (i, j) 的最大分數
dp2[i][j] := 從 (i, j) 到 (n, m) 的最大分數
dp3[i][j] := 從 (n, 1) 到 (i, j) 的最大分數
dp4[i][j] := 從 (i, j) 到 (1, m) 的最大分數

代碼:

技術分享圖片
 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 using namespace std;
 5 const int maxn=1e3+5;
 6 int a[maxn][maxn];
 7 int dp1[maxn][maxn];//(1,1)-(i,j)
 8 int dp2[maxn][maxn];//(i,j)-(1,1)
 9 int dp3[maxn][maxn];//(n,1)-(i,j)
10 int dp4[maxn][maxn];//(i,j)-(n,1)
11
int main() 12 { 13 int n,m; 14 scanf("%d%d",&n,&m); 15 for(int i=1;i<=n;i++) 16 for(int j=1;j<=m;j++) scanf("%d",&a[i][j]); 17 for(int i=1;i<=n;i++) 18 for(int j=1;j<=m;j++) dp1[i][j]=a[i][j]+max(dp1[i][j-1],dp1[i-1][j]); 19 for(int i=n;i>=1
;i--) 20 for(int j=m;j>=1;j--) 21 dp2[i][j]=a[i][j]+max(dp2[i][j+1],dp2[i+1][j]); 22 for(int i=n;i>=1;i--) 23 for(int j=1;j<=m;j++) 24 dp3[i][j]=a[i][j]+max(dp3[i+1][j],dp3[i][j-1]); 25 for(int i=1;i<=n;i++) 26 for(int j=m;j>=1;j--) 27 dp4[i][j]=a[i][j]+max(dp4[i][j+1],dp4[i-1][j]); 28 int ans=0; 29 for(int i=2;i<n;i++) 30 for(int j=2;j<m;j++) 31 { 32 ans=max(ans,dp1[i][j-1]+dp2[i][j+1]+dp3[i+1][j]+dp4[i-1][j]); 33 ans=max(ans,dp3[i][j-1]+dp4[i][j+1]+dp2[i+1][j]+dp1[i-1][j]); 34 } 35 printf("%d\n",ans); 36 return 0; 37 }
View Code

樣例中的dp1,dp2,dp3,dp4最終結果為:

100 200 300
200 201 400
300 400 500

500 400 300
400 201 200
300 200 100

300 400 500
200 201 400
100 200 300

300 200 100
400 201 200
500 400 300

在最終求出結果時:

for(int i=2;i<n;i++)
{

  for(int j=2;j<m;j++)
  {
    ans=max(ans,dp1[i][j-1]+dp2[i][j+1]+dp3[i+1][j]+dp4[i-1][j]);
    ans=max(ans,dp3[i][j-1]+dp4[i][j+1]+dp2[i+1][j]+dp1[i-1][j]);
  }

}

第一種情況下的ans的值為黃色部分值相加,第二種情況下的ans的值為藍色部分值相加;

Working out(DP)