CodeForces - 429B Working out(dp)
阿新 • • 發佈:2018-11-10
看到題目,沒什麼思路
看了大佬部落格:https://blog.csdn.net/xiaolonggezte/article/details/69145427,豁然開朗,還是有些小問題沒注意,wa了挺久
題意:
在n*m的格子裡,A從(1,1)到(n,m),B從(n,1)到(1,m),
A只能從 (i, j) 到 (i+1 , j) 或者 (i, j+1),B只能從 (i, j) 到 (i-1, j) 或者 (i, j+1)
A和B的路線有且只有一點重合,並且這一點不在A和B的起點或終點,
求怎樣走使A和B的路線的權值之和(重合點的權值不計算)最大
思路:
把路線分成四段,設重合點為x,計算 (1,1)到x,(n,m)到x,(1,m)到x,(n,1)到x 四段路的權值和;
注意:
重合的點不在邊界,並且只有一個點重合!
#include <iostream> #include <cstring> #include <algorithm> using namespace std; typedef long long ll; ll dp1[1100][1100],dp2[1100][1100],dp3[1100][1100],dp4[1100][1100]; //重合的點為x,dp1:(1,1)到x,dp2:(n,m)到x,dp3:(n,1)到x,dp4: (1,m)到x ll a[1100][1100]; int main() { memset(dp1,0,sizeof(dp1)); memset(dp2,0,sizeof(dp2)); memset(dp3,0,sizeof(dp3)); memset(dp4,0,sizeof(dp4)); int n,m; cin>>n>>m; for(int i = 1;i <= n;i++) for(int j = 1;j <= m;j++) cin>>a[i][j]; for(int i = 1;i <= n;i++) for(int j = 1;j <= m;j++) dp1[i][j] = max(dp1[i-1][j],dp1[i][j-1])+a[i][j]; for(int i = n;i > 0;i--) for(int j = m;j > 0;j--) dp2[i][j] = max(dp2[i+1][j],dp2[i][j+1])+a[i][j]; for(int i = n;i > 0;i--) for(int j = 1;j <= m;j++) dp3[i][j] = max(dp3[i+1][j],dp3[i][j-1])+a[i][j]; for(int i = 1;i <= n;i++) for(int j = m;j > 0;j--) dp4[i][j] = max(dp4[i-1][j],dp4[i][j+1])+a[i][j]; ll ans = 0; //注意(i,j)不在邊界 for(int i = 2; i < n; i ++) for(int j = 2; j < m; j ++) { //除了(i,j)外的點不能再重合,所以一共就兩種走法 ,沒考慮路徑,直接用和-4*a[i][j],wa瘋 ans = max(ans,dp1[i - 1][j] + dp2[i + 1][j]+dp3[i][j - 1] + dp4[i][j + 1]); ans = max(ans,dp1[i][j - 1] + dp2[i][j + 1] + dp3[i + 1][j] + dp4[i - 1][j]); } cout<<ans<<endl; return 0; }