题解
一道矩阵dp的升级版,难在来回两次怎么办?
想想可知来回其实就等价于走两次,怎样表示走两次呢?这又是个问题。
走一次的所有阶段和状态可以由二维数组解决,那么两次是不是可以用四维数组搞定呢。没错就是这么暴力。
定义 F [ i , j , k , q ] 为 第一走到[ i , j ] 第二走到[ k , q ] 时最大的积累值
那么就有状态转移方程
F [ i , j , k , q ] = max( F [ i-1 , j , k-1 , q ] ,F [ i -1, j , k , q-1 ] ,
F [ i , j-1 , k-1 , q ] ,F [ i , j-1 , k , q-1 ] ) + a[ i, j ] + a[ k , q]
当然还要解决一下 相遇问题,这个非常简单只要当位置重合时,将算得的累计值减去a[ i, j ] 或 a[ k , q]之一就好。
ps: 后续的代码用的时三维数组,这问题可优化成三维的,因为当以步数衡量时,知道x坐标的时候y坐标是显然的。
Code
// head files
using namespace std;
int n,m;
int cot[52][52];
int f[150][52][52];
int max_of(int a,int b,int c,int d){
return max(max(a,b),max(c,d));
}
int main(){
cin>>n>>m;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++)
cin>>cot[i][j];
}
for(int k=1;k<= n+m-1;k++){
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if( k-i+1<1 || k-j+1 <1 ) continue;// out of range exclude
f[k][i][j]=max_of(f[k-1][i][j],f[k-1][i-1][j-1],
f[k-1][i][j-1], f[k-1][i-1][j]
) + cot[i][k-i+1]+cot[j][k-j+1];
if(i==j) // 相遇
f[k][i][j] -= cot[i][k-i+1];
}
}
}
cout<<f[n+m-1][n][n]<<endl;
return 0;
}