《算法竞赛进阶指南》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;
}
原文地址:https://www.cnblogs.com/randy-lo/p/13388361.html