【DP】noip 2008 T3 luogu P1006 传纸条

题面

在这里插入图片描述

分析

由于做过noip 2000 Day2 T6 方格取数
看到这道题的第一反映就是棋盘DP,
将方格取数的方程套用过来就有

f [ i ] [ j ] [ k ] [ l ] = m a x ( s i t i u a t i o n 1 , s i t i u a t i o n 2 ) + w f[i][j][k][l]=max(sitiuation1,sitiuation2)+w f[i][j][k][l]=max(sitiuation1,sitiuation2)+w
w = ( 第 一 个 人 和 第 二 个 人 在 同 一 位 置 ) ? G [ i ] [ j ] : G [ i ] [ j ] + G [ k ] [ l ] w=(第一个人和第二个人在同一位置)?G[i][j]:G[i][j]+G[k][l] w=()G[i][j]:G[i][j]+G[k][l]
s i t i u a t i o n 1 = m a x ( f [ i ] [ j − 1 ] [ k ] [ l − 1 ] , f [ i ] [ j − 1 ] [ k − 1 ] [ l ] ) sitiuation1=max(f[i][j-1][k][l-1],f[i][j-1][k-1][l]) sitiuation1=max(f[i][j1][k][l1],f[i][j1][k1][l])
s i t i u a t i o n 2 = m a x ( f [ i − 1 ] [ j ] [ k ] [ l − 1 ] , f [ i − 1 ] [ j ] [ k − 1 ] [ l ] ) sitiuation2=max(f[i-1][j][k][l-1],f[i-1][j][k-1][l]) sitiuation2=max(f[i1][j][k][l1],f[i1][j][k1][l])

这样子做的正确性就在于,一条从左上角到右下角的路线和另一条从右下角到左上角的路线严格不相交,其最大权值和,其实就等价于两条从左上角到右下角的严格不相交路线的最大权值和

只是这个严格不相交的实现是个麻烦点

但事实上只需要在枚举 l l l的时候将枚举起始点改为j+1即可
这样的话,就把第二个人可以行走的空间限制在了第一个人走的路线的右上方(图中),也就排除了相交的可能。并且由于第一个人行走的空间范围被枚举,于是限制 l l l也就不会使可能性减少
当然,由于第二个人的路线其实和第一个人的是等价的,于是最终状态就是 f [ n ] [ m − 1 ] [ n − 1 ] [ m ] f[n][m-1][n-1][m] f[n][m1][n1][m]

code

#include<bits/stdc++.h>
using namespace std;
#define loop(i,start,end) for(int i=start;i<=end;i++)
#define anti_loop(i,start,end) for(int i=start;i>=end;i--)
#define clean(arry,num); memset(arry,num,sizeof(arry));
#define min(a,b) ((a<b)?a:b)
#define max(a,b) ((a>b)?a:b)
#define ll long long
const int maxn=55;
const int maxm=55; 
int n,m;
int f[maxn][maxm][maxn][maxm];
int g[maxn][maxm];
inline int read()
{
	int neg=1;int ans=0;char r=getchar();
	while(r>'9'||r<'0'){if(r=='-')neg=-1;r=getchar();}
	while(r>='0'&&r<='9'){ans=ans*10+r-'0';r=getchar();}
	return ans*neg;
}
int main()
{
	//freopen("datain.txt","r",stdin);
	n=read();m=read();clean(f,0);clean(g,-1);
	loop(i,1,n)loop(j,1,m)g[i][j]=read();
	loop(i,1,n)
	{
		loop(j,1,m)
		{
			loop(k,1,n)
			{
				loop(z,j+1,m)
				{
					
					f[i][j][k][z]=max(max(f[i-1][j][k-1][z],f[i-1][j][k][z-1]),max(f[i][j-1][k-1][z],f[i][j-1][k][z-1]))+g[i][j]+g[k][z];				
				}
			}
		}
	}
	printf("%d",f[n][m-1][n-1][m]);
	return 0;
}

学到的东西

1.不要把方程打错了!!

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

AndrewMe8211

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值