做题记录整理dp6 P1006. [NOIP2008 提高组] 传纸条(2022/9/20)

P1006. [NOIP2008 提高组] 传纸条

算是一个寻找最大权值的路径的变式

我们可以想到,把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;
}
posted @ 2022-09-20 17:31  yyx525jia  阅读(38)  评论(0)    收藏  举报