一个经典的dp题,典型的错误思想就是做两遍
我们考虑直接做,f[i][j][x][y]表示第一次取道i,j这个位置,第二次到了x,y这个位置
考虑这个i,j和x,y分别是从哪里转移过来,就可以得到方程
f[i][j][x][y]=max(f[i-1][j][x-1][y],f[i][j-1][x-1][y],f[i-1][j][x][y-1],f[i][j-1][x][y-1])+v[x][y]+v[i][j]
这个方程显然有x+y=i+j那么考虑去掉j,y这一维
令f[k][i][j]表示走了k步,分别走到第i行,第j行的答案,转移可以写成
f[k][i][j]=max(f[k-1][i][j],f[k-1][i-1][j-1],f[k-1][i-1][j],f[k-1][i][j-1])+s[i][k-i]+s[j][k-j]
注意如果i=j那么最后那个s[j][k-j]不要加,滚动一下就可以过了
当然这题也有网络流做法,非常的类似:
#pragma GCC opitmize("O3")
#pragma G++ opitmize("O3")
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
int n,m,f[210][210],s[210][210];
int main(){
scanf("%d%d",&m,&n);
for(int i=1;i<=n;++i)
for(int j=1;j<=m;++j) scanf("%d",s[i]+j);
for(int k=2;k<=m+n;++k) for(int i=n;i;--i) for(int j=n;j;--j)
f[i][j]=max(max(f[i][j],f[i-1][j-1]),max(f[i-1][j],f[i][j-1]))+s[i][k-i]+(i!=j?s[j][k-j]:0);
printf("%d\n",f[n][n]);
}
1153



被折叠的 条评论
为什么被折叠?



