Working out CodeForces - 429B(四个角递推+dp)

传送门

题意:要求两个人必须相遇一次,A这个人只能从[1,1]到[n,m],B这个人只能从[n,1]到[1,m],A只能向下向右走,B只能向上向右走,问如何选取使得最后值最大。

题解:先分别从四个递推,然后枚举相遇的块,相遇的块肯定不能是边界,因为边界必然有多个块相碰,只能枚举中间的块,但是中间的块对于A只能向下或者向右,如果A是从上面来的,那么必然B是从右边来的,并且A继续向下走,B继续向右走,才能保证只有一个块相碰,如果A是向右走的,那么B必然是从下面来的,A也必须继续向右走,B也必须向上走才能保证只有一个块相遇,最后导出答案即可。

附上代码:


#include<bits/stdc++.h>

using namespace std;

const int maxn=1e3+5;

int n,m;
int mapp[maxn][maxn];
int dp1[maxn][maxn],dp2[maxn][maxn],dp3[maxn][maxn],dp4[maxn][maxn];
int ans;

int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            scanf("%d",&mapp[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])+mapp[i][j];
        }
    }
    for(int i=n;i>=1;i--){
        for(int j=m;j>=1;j--){
            dp2[i][j]=max(dp2[i+1][j],dp2[i][j+1])+mapp[i][j];
        }
    }
    for(int i=n;i>=1;i--){
        for(int j=1;j<=m;j++){
            dp3[i][j]=max(dp3[i+1][j],dp3[i][j-1])+mapp[i][j];
        }
    }
    for(int i=1;i<=n;i++){
        for(int j=m;j>=1;j--){
            dp4[i][j]=max(dp4[i-1][j],dp4[i][j+1])+mapp[i][j];
        }
    }
    for(int i=2;i<n;i++){
        for(int j=2;j<m;j++){
            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]);
        }
    }
    printf("%d\n",ans);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/zhouzi2018/article/details/86485317