《算法竞赛进阶指南》0x51线性DP 传纸条
题目要求:给一个n*m的矩阵,求从左上角到右下角的两条路径,使得两条路径上的值只和最大。从左上角往右下角走的时候只能向下或者向右。
在这个问题中阶段就是步数,步数与坐标点的横纵坐标之和相差一个常数,所以可以通过坐标只和以及两个点的横坐标来确定当前的状态集合。此时通过一个点的所有入边更新一个点即可。一共有四种状态,代价可以先计算出来。其中坐标枚举的范围要综合考虑横纵坐标的范围。
代码:
#include<iostream> #include<cstdio> #include<string.h> using namespace std; const int maxn = 56; int n,m; int w[maxn][maxn]; int f[maxn<<1][maxn][maxn]; int main(){ cin>>n>>m; for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) cin>>w[i][j]; for(int k=2;k<=n+m;k++) for(int x1=max(1,k-m);x1<=min(n,k-1);x1++) for(int x2=max(1,k-m);x2<=min(n,k-1);x2++){ int t=w[x1][k-x1]; if(x1!=x2)t+=w[x2][k-x2]; for(int a=0;a<=1;a++) for(int b=0;b<=1;b++) f[k][x1][x2]=max(f[k][x1][x2],f[k-1][x1-a][x2-b]+t); } cout<<f[n+m][n][n]<<endl; }