有两条路径,设上面的路径为路径1,下面的为路径2,路径1上的点为x1,y1,路径2上的点为x2,y2
dp[i][j][k]表示x1,x2,step
由step可以确定出y1和y2,这样可以缩小一维,本来暴力起来应该是200的四次方,16亿,肯定爆内存。
然后对于每个状态,可以由step-1的四种状态(↓↓,↓→,→→,→↓)更新过来,更新过程中注意判断一下边界条件别RE就可以了,复杂度O(n3)可以接受。
另外还有个细节处理,就是把头和尾给单独拿出来了,因为情况比较特殊。
#include <iostream>
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <string>
#include <string.h>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <stack>
#include <bits/stdc++.h>
using namespace std;
int N;
int F[204][204];
int dp[204][204][404];//x1(topLine),x2(bottomLine),step
int main(){
cin>>N;
for(int i=0;i<N;i++){
for(int j=0;j<N;j++){
scanf("%d",&F[i][j]);
}
}
if(N<=2){
int sum=0;
for(int i=0;i<N;i++){
for(int j=0;j<N;j++){
sum+=F[i][j];
}
}
cout<<sum<<endl;
return 0;
}
memset(dp,0,sizeof(dp));
dp[1][0][1]=F[0][0]*2+F[0][1]+F[1][0];
for(int i=2;i<N*2-2;i++){//step
for(int j=1;j<=N-1;j++){//x1
int y1=i-j;
if(y1<0)break;
for(int k=0;k<j;k++){//x2
int y2=i-k;
int v1=F[j][y1];
int v2=F[k][y2];
if(y1>0){
dp[j][k][i]=max(dp[j][k][i],dp[j][k][i-1]+v1+v2);//1向下2向下更新
if(k>0){
dp[j][k][i]=max(dp[j][k][i],dp[j][k-1][i-1]+v1+v2);//1向下2向右
}
}
if(k>0&&j>=2){
dp[j][k][i]=max(dp[j][k][i],dp[j-1][k-1][i-1]+v1+v2);//向右向右
}
if(j>=2&&j-k>1){
dp[j][k][i]=max(dp[j][k][i],dp[j-1][k][i-1]+v1+v2);//向右向下
}
}
}
}
cout<<dp[N-1][N-2][N*2-3]+2*F[N-1][N-1]<<endl;
return 0;
}
//
// _oo0oo_
// o8888888o
// 88" . "88
// (| -_- |)
// 0\ = /0
// ___/`---'\___
// .' \\| |// '.
// / \\||| : |||// \
// / _||||| -:- |||||- \
// | | \\\ - /// | |
// | \_| ''\---/'' |_/ |
// \ .-\__ '-' ___/-. /
// ___'. .' /--.--\ `. .'___
// ."" '< `.___\_<|>_/___.' >' "".
// | | : `- \`.;`\ _ /`;.`/ - ` : | |
// \ \ `_. \_ __\ /__ _/ .-` / /
// =====`-.____`.___ \_____/___.-`___.-'=====
// `=---='
//
//
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// 佛祖保佑 永无BUG
//
//
//