Codeforces 429B Working out【基礎DP】
阿新 • • 發佈:2018-11-09
B. Working out
給n*m的矩陣,每個格子有個數,A從(1,1)出發只能向下或右走,終點為(n,m),B從(n,1)出發只能向上或右走,終點為(1,m)。兩個人的速度不一樣,走到的格子可以獲的該格子的數,兩人相遇的格子上的數兩個人都不能拿。求A和B能拿到的數的總和的最大值。
n,m<=1000
Sample test(s)
input
3 3
100 100 100
100 1 100
100 100 100
output
800
解題思路:dp。先預處理出每個格子到四個角落格子的路徑最大數值,然後列舉兩個人相遇的交點格子,列舉A、B的進來和出去方式,求最大值即可。注意邊界情況。 https://blog.csdn.net/cc_again/article/details/25691925
#include<iostream> #include<algorithm> #include<cstring> using namespace std; typedef long long ll; const int N=1010; const int INF=0x3f3f3f; ll dp[4][N][N],a[N][N]; int main() { int n,m; while(~scanf("%d%d",&n,&m)){ for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) scanf("%lld",&a[i][j]); memset(dp,0,sizeof(dp)); //求從點(x,y)到左上、右上、左下、右下四個角能獲取的最大和,分別儲存在dp[0~3][i][j] for(int i=1;i<=n;i++){ //從左上角落到(x,y) for(int j=1;j<=m;j++) dp[0][i][j]=max(dp[0][i][j-1],dp[0][i-1][j])+a[i][j]; //從右上角落到(x,y) for(int j=m;j>0;j--) dp[1][i][j]=max(dp[1][i][j+1],dp[1][i-1][j])+a[i][j]; } for(int i=n;i>0;i--){ //從左下角落到(x,y) for(int j=1;j<=m;j++) dp[2][i][j]=max(dp[2][i][j-1],dp[2][i+1][j])+a[i][j]; //從右下角落到(x,y) for(int j=m;j>0;j--) dp[3][i][j]=max(dp[3][i][j+1],dp[3][i+1][j])+a[i][j]; } //處理邊界:方便列舉 for(int i=0;i<=n+1;i++) for(int j=0;j<4;j++) dp[j][i][0]=dp[j][i][m+1]=-INF; for(int i=0;i<=m+1;i++) for(int j=0;j<4;j++) dp[j][0][i]=dp[j][n+1][i]=-INF; ll res=0; //列舉每個點 ,是相遇的點 (只考慮在一個格子相遇的情況,因此只有兩種情況) for(int i=1;i<=n;i++) for(int j=1;j<=m;j++){ ll val=dp[0][i][j-1]+dp[3][i][j+1]+dp[2][i+1][j]+dp[1][i-1][j]; res=max(res,val); val=dp[0][i-1][j]+dp[3][i+1][j]+dp[2][i][j-1]+dp[1][i][j+1]; } printf("%lld\n",res); } return 0; }