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;
}

猜你喜欢

转载自www.cnblogs.com/mrasd/p/9550022.html