Luogu1006 传纸条(4维dp)

it2022-07-02  245

题目链接:

https://www.luogu.org/problem/P1006

题意:

一个n*m的网格,每个格子有一个值,要求从左上(1,1)找到两条到右下(m,n)不重合的路径且两条路径上格子的值的和最大,每次移动只能向下或向右(0<=m,n<=50),起点(1,1)和终点(m,n)的值为0。

题解:

显然可以用四维dp(当然有些机智的巨佬发现可以用三维dp),一条路径走到(i,j),另一条走到(k,t),因为不能重合,所以第四重循环的t要从j+1开始,因为第一条路径走到(i,j)时,以(1,1),(1,j),(i,1),(i,j)为顶点的矩形内的点都已被第一条路径走过,而且以(1,1),(1,n),(i,1),(i,n)为顶点的矩形内还未走的点将被第一条路径走过。

状态转移方程:

dp[i][j][k][t]=max(dp[i-1][j][k-1][t]+a[i][j]+a[k][t],dp[i-1][j][k][t-1]+a[i][j]+a[k][t],dp[i][j-1][k-1][t]+a[i][j]+a[k][t],dp[i][j-1][k][t-1]+a[i][j]+a[k][t])

代码:

#include <iostream> #include <cstdlib> #include <algorithm> using namespace std; int dp[55][55][55][55]; int s[55][55]; int main() { int m,n; int a[55][55]; cin>>n>>m; for(int i=1;i<=n;i++) { for(int j=1;j<=m;j++) cin>>a[i][j]; } for(int i=1;i<=n;i++) { for(int j=1;j<=m;j++) { for(int k=1;k<=n;k++) { for(int t=j+1;t<=m;t++) dp[i][j][k][t]=max(dp[i-1][j][k-1][t]+a[i][j]+a[k][t],max(dp[i-1][j][k][t-1]+a[i][j]+a[k][t],max(dp[i][j-1][k-1][t]+a[i][j]+a[k][t],dp[i][j-1][k][t-1]+a[i][j]+a[k][t]))); } } } cout<<dp[n][m-1][n-1][m]; return 0; }

最新回复(0)