Working out

题意:一个人从左上走到右下,一个人从左下走到右上,两个人必须有一个点作为见面点,见面点的权值不能拿,问按照规则走,取得最大权值的和为多少

只是考虑左上角那个点的话起点记作start,假设在(i,j)点处相遇,这个点记作now,然后继续走到终点右下角记作end,那么是不是这条路线的和就应该是start->now + now -> end这两段的数值的和,当然了不加now那个点;

那我们再想,start->now这个点我们已经用dp求出来了,其实now->end的总数值是不是就等于end->now的总数值,因此我们可以转化为求end->now的最大值,那么这个问题也就转化成了矩阵的四个角分别求dp,然后枚举每个点为相遇点,比较得出最大的即可

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int Max = 1e3+10;
int mp[Max][Max];
int dp1[Max][Max],dp2[Max][Max],dp3[Max][Max],dp4[Max][Max];
int n,m;
int main(){
    int i,j;
    cin >> n >> m;
    memset(mp,0,sizeof(mp));
    for(i = 1; i <= n; i++){
        for(j = 1; j <= m; j++){
            cin >> mp[i][j];
        }
    }
    //左上角求dp1
    memset(dp1,0,sizeof(dp1));
    for(i = 1; i <= n; i++){
        for(j = 1; j <= m; j++){
            dp1[i][j] = max(dp1[i-1][j],dp1[i][j-1]) + mp[i][j];
        }
    }
    //左下角求dp2
    memset(dp2,0,sizeof(dp2));
    for(i = n; i >= 1; i--){
        for(j = 1; j <= m; j++){
            dp2[i][j] = max(dp2[i+1][j],dp2[i][j-1]) + mp[i][j];
        }
    }
    //右上角求dp3
    memset(dp3,0,sizeof(dp3));
    for(i = 1; i <= n; i++){
        for(j = m; j >= 1; j--){
            dp3[i][j] = max(dp3[i-1][j],dp3[i][j+1]) + mp[i][j];
        }
    }
    //右下角求dp4
    memset(dp4,0,sizeof(dp4));
    for(i = n; i >= 1; i--){
        for(j = m; j >= 1; j--){
            dp4[i][j] = max(dp4[i+1][j],dp4[i][j+1]) + mp[i][j];
        }
    }
    //枚举每个相遇点求出总和,并比较选出最大值
    int Max = -1;
    for(i = 2; i < n; i++){
        for(j = 2; j < m; j++){
             Max = max(Max,dp1[i-1][j]+dp2[i][j-1]+dp3[i][j+1]+dp4[i+1][j]);
            Max = max(Max,dp1[i][j-1]+dp2[i+1][j]+dp3[i-1][j]+dp4[i][j+1]);
        }
    }
    cout << Max << endl;
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qie_wei/article/details/86547393
今日推荐