本体思路解析:首先看到题目的数据范围,就知道应该可以使用多维的动态规划了。
这里第一点想说的就是,这题可以等价于两个人一起从左上往下走,
而且这样更方便判断(用心感受一下),
那么这里有两个选择1:四维2:三维 你选哪个?很明显选三维。。。
毕竟是n^3的空间和时间。不过四维的思路还是讲一下:
dp[a][b][c][d]表示去到(a,b)和(c,d)两对点时的最大好心度,
说白了就是枚举坐标,然后通过上一个点状态转移过来,
上一个点:(a-1,b)或(a,b-1),c,d同理。
那么这里我们遇到了本题的难点了,
如果使用4维的话,那么你很好判断点是否是重复的,
直接在状态转移的时候加一个if判断就好了,
判断上一个状态合不合法,(两个人经过相同点显然是不合法的)。
那么介绍一下这道题目前我掌握的最优解,就是一个3维的做法了。
我们可以看出,每次移动都是让两个人的x或y加一那么从起点开始两个人的x+y是一个定值,
也就是你四维枚举的那些不存在的情况已经被消灭了,比如四维[1][1][100][100]这显然是不可能的嘛,
怎么可能你走了那么远我还在原地啊。所以三维的优化就是在这里,你可别小看这一维哦。
好,那么老问题,怎么判断合法呢?这就更好判断了,三维的思路是枚举一个点的x,y坐标和另一个点的x坐标
,只要两个x坐标不一样就好啦(已经证明了x+y是一个定值),
最后只要算出终点左边和上面的最大好心值之和就行了,因为最后一个点可能会被“吃

//AC Code:
#include <cstdio>
using namespace std;
int n,m,nm[55][55],dp[55][55][55];
int max(int a,int b){
    return a>b?a:b;
}
int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)scanf("%d",&nm[i][j]);
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            for(int k=1;k<=n;k++){
                if(i!=k){
                    int a=max(dp[i-1][j][k-1],dp[i-1][j][k])+nm[i][j]+nm[k][i+j-k];
                    int b=max(dp[i][j-1][k-1],dp[i][j-1][k])+nm[i][j]+nm[k][i+j-k];
                    dp[i][j][k]=max(a,b);
                }
            }
            
    /*for(int i=n;i>=1;i--){
        for(int j=m;j>=1;j--){
            d2[i][j]=max(dp[i+1][j],dp[i][j+1],i,j)+nm[i][j];
        }
    }*/
    printf("%d",dp[n][m-1][n-1]);
    return 0;
}