Codeforces 429B B. Working out

动态规划专题

推荐做这道题

其实就是简单的方格取数×4+枚举
四次方格取数从不同的角落出发,到达每个点。用四个数组存。
f [ k ] [ i ] [ j ] 表示从第k个角到点(i,j)的最大权值路径。
我们这里使f[1]是左上,f[2]左下,f[3]右上,f[4]右下(但代码里可能不是这样)
然后,就二重循环枚举每个点(i,j)。因为两个交叉1个点以上就不划算,所以只考虑一个的情况。
又有,A只能从上面和左边来,B只能从下面和左边来,那么就只有两种情况。
1、A从上面来下面出去,B从左边来右面出去。
2、A从左面来右面出去,B从上边来下边出去。
然后将两种情况的值算出来,取较大的,再在所有的里面去最大的。
source:

#include<iostream>
#include<cstdio>
#include<algorithm>
#define inf 0x3f3f3f3f
#define ll long long
using namespace std;
ll f[5][1005][1005],a[1005][1005],n,m;
int main(){
    scanf("%lld%lld",&n,&m);
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            scanf("%lld",&a[i][j]);
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
            f[1][i][j]=max(f[1][i-1][j],f[1][i][j-1])+a[i][j];
        for(int j=m;j>=1;j--)
            f[3][i][j]=max(f[3][i-1][j],f[3][i][j+1])+a[i][j];
    }
    for(int i=n;i>=1;i--)
    {
        for(int j=1;j<=m;j++)
            f[2][i][j]=max(f[2][i+1][j],f[2][i][j-1])+a[i][j];
        for(int j=m;j>=1;j--)
            f[4][i][j]=max(f[4][i+1][j],f[4][i][j+1])+a[i][j];
    }

    for(int i=0;i<=n;i++)
        for(int k=1;k<=4;k++)
            f[k][i][0]=f[k][i][m+1]=-inf;
    for(int j=0;j<=m;j++)
        for(int k=1;k<=4;k++)
            f[k][0][j]=f[k][n+1][j]=-inf;

    ll ans=-inf;
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
        {
            ans=max(ans,f[1][i][j-1]+f[4][i][1+j]+f[3][i-1][j]+f[2][i+1][j]);
            ans=max(ans,f[1][i-1][j]+f[4][i+1][j]+f[2][i][j-1]+f[3][i][j+1]);
        }
    }
    printf("%lld",ans);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/jiangbojun2017/article/details/82150457