Working out(DP)
阿新 • • 發佈:2019-02-14
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) 11View Codeint 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 }
樣例中的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)