做题记录整理dp6 P1006. [NOIP2008 提高组] 传纸条(2022/9/20)
算是一个寻找最大权值的路径的变式
我们可以想到,把n,m这张倒过来,就变成了两个人同一个起点,走到同一个终点,只要路径不重合就可以了
先设一个暴力的方程dpi,j,k,l表示第一个人走到i,j,第二个人走到k,l的最大权值和
dp[i][j][k][l]=max(dp[i][j-1][k][l-1],dp[i][j-1][k-1][l],dp[i-1][j][k-1][l],dp[i-1][j][k-1][l])+a[i][j]+b[k][l];
这里的b是a倒过来的图
我们会发现,MLE了,所以就优化一下
dp[i][j][k]=max(dp[i-1][j-1][k],dp[i-1][j-1][k-1],dp[i-1][j][k-1],dp[i-1][j][k])+a[i-j][j]+b[i-k][k];
这里的dpi,j,k表示两个人都走了i步,第一个人走了i步向右,第二个人走了k步向右
#include<bits/stdc++.h>
using namespace std;
int dp[200][100][100],a[100][100],n,m,k,cz,x,y;
int main()
{
scanf("%d%d",&m,&n);
for(int i = 1;i<= m;i++)
for(int j = 1;j <=n;j++)
scanf("%d",&a[i][j]);
memset(dp,-1,sizeof(dp));
dp[2][1][1] = 0;
for(int k = 3;k <m+n;k++)
{
for(int i = 1;i <n;i++)
{
for(int j = i+1;j<=n;j++)
{
int s = dp[k][i][j];
if(dp[k-1][i][j]>s)s=dp[k-1][i][j];
if(dp[k-1][i-1][j]>s)s=dp[k-1][i-1][j];
if(dp[k-1][i][j-1]>s)s=dp[k-1][i][j-1];
if(dp[k-1][i-1][j-1]>s)s=dp[k-1][i-1][j-1];
if(s == -1) continue;
dp[k][i][j] = s + a[k-i][i]+ a[k-j][j];
}
}
}
cout<<dp[m+n-1][n-1][n];
return 0;
}

浙公网安备 33010602011771号