luogu P1006 传纸条
luogu P1006 传纸条
题意
从一个矩形中选出不相交的两条从左上角到右下角的路径,求可以选出的最大权值和。
解法
这道题与P1004 方格取数一模一样,我们可以设一个4维dp: \(dp[i][j][k][l]\) 表示第一条路径我们走到了(i,j)处,第二条路径我们走到了(k,l)处,这样我们有转移方程:
\(dp[i][j][k][l] = max(dp[i-1][j][k-1][l],dp[i][j-1][k-1][l],dp[i-1][j][k][l-1],dp[i][j-1][k][l-1]) + a[i][j] + a[k][l]\)
\(if(i==k,j==l) dp[i][j][k][l] -= a[i][j]\)
这样就可以过这道题了。
代码
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <cctype>
#define INF 2139062143
#define MAX 0x7ffffffffffffff
#define del(a,b) memset(a,b,sizeof(a))
using namespace std;
typedef long long ll;
template<typename T>
inline void read(T&x)
{
x=0;T k=1;char c=getchar();
while(!isdigit(c)){if(c=='-')k=-1;c=getchar();}
while(isdigit(c)){x=x*10+c-'0';c=getchar();}x*=k;
}
const int maxn=50+5;
int a[maxn][maxn];
int dp[maxn*2][maxn][maxn];
int n,m;
int main()
{
read(n),read(m);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
read(a[i][j]);
for(int k=2;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;
dp[k][i][j]=max(max(dp[k-1][i][j],dp[k-1][i-1][j-1]),max(dp[k-1][i-1][j],dp[k-1][i][j-1]))+
a[i][k-i+1]+a[j][k-j+1];
if(i==j) dp[k][i][j]-=a[j][k-j+1];
}
printf("%d",dp[n+m-1][n][n]);
return 0;
}