洛谷 P5851 [USACO19DEC]Greedy Pie Eaters P(区间 dp)

题目链接

题意:有 \(n\) 个派。\(m\) 头牛要吃这些派,第 \(i\) 头牛体重(权值?英文是 weight)为 \(w_i\),喜欢吃 \([l_i,r_i]\) 的派。轮到第 \(j\) 头牛的时候,它会吃掉所有在 \([l_j,r_j]\) 中未吃掉的派。
现在 FJ 要选出一些牛出来,让它们按一定顺序吃,并且每头奶牛都吃掉至少一个派。求选出的奶牛的体重和的最大值。
\(1 \leq n \leq 300\)

题解:设 \(dp_{l,r}\) 为吃掉 \([l,r]\) 能够获得的最体重和的最大值。
很显然可以枚举断点 \(k\)\(dp_{l,r}=\max\limits_{k=l}^rdp_{l,k-1}+dp_{k+1,r}+f_{k,l,r}\)
其中 \(f_{k,l,r}\)\(l \leq l_i \leq k \leq r_i \leq r\)\(i\) 中,最大的 \(w_i\)
\(f\) 数组可通过另一个区间 \(dp\) 求得:\(f_{k,l,r}=\max(f_{k,l-1,r},f_{k,l,r+1})\),初值 \(f_{k,l_i,r_i}=w_i\)\(l_i \leq k \leq r_i\)

#include <bits/stdc++.h>
using namespace std;
#define fi			first
#define se			second
#define fz(i,a,b)	for(int i=a;i<=b;i++)
#define fd(i,a,b)	for(int i=a;i>=b;i--)
#define foreach(it,v) for(__typeof(v.begin()) it=v.begin();it!=v.end();it++)
#define all(a)		a.begin(),a.end()
#define giveup(...) return printf(__VA_ARGS__),0;
#define fill0(a)	memset(a,0,sizeof(a))
#define fill1(a)	memset(a,-1,sizeof(a))
#define fillbig(a)	memset(a,0x3f,sizeof(a))
#define fillsmall(a) memset(a,0xcf,sizeof(a))
#define mask(a)		(1ll<<(a))
#define maskx(a,x)	((a)<<(x))
#define _bit(a,x)	(((a)>>(x))&1)
#define _sz(a)		((int)(a).size())
#define filei(a)	freopen(a,"r",stdin);
#define fileo(a)	freopen(a,"w",stdout);
#define fileio(a) 	freopen(a".in","r",stdin);freopen(a".out","w",stdout)
#define eprintf(...) fprintf(stderr,__VA_ARGS__)
#define put(x)		putchar(x)
#define eoln        put('\n')
#define space		put(' ')
#define y1			y_chenxiaoyan_1
#define y0			y_chenxiaoyan_0
typedef pair<int,int> pii;
inline int read(){
	int x=0,neg=1;char c=getchar();
	while(!isdigit(c)){
		if(c=='-')	neg=-1;
		c=getchar();
	}
	while(isdigit(c))	x=x*10+c-'0',c=getchar();
	return x*neg;
}
inline void print(int x){
	if(x<0){
		putchar('-');
		print(abs(x));
		return;
	}
	if(x<=9)	putchar(x+'0');
	else{
		print(x/10);
		putchar(x%10+'0');
	}
}
inline int qpow(int x,int e,int _MOD){
	int ans=1;
	while(e){
		if(e&1)	ans=ans*x%_MOD;
		x=x*x%_MOD;
		e>>=1;
	}
	return ans;
}
int n=read(),m=read();
int f[305][305][305],dp[305][305];
signed main(){
	fz(i,1,m){
		int w=read(),l=read(),r=read();
		fz(j,l,r)	f[j][l][r]=max(f[j][l][r],w);
	}
	fz(_,1,n)	fz(len,1,n)	for(int i=1,j=len;j<=n;i++,j++){
		if(i!=1)	f[_][i-1][j]=max(f[_][i-1][j],f[_][i][j]);
		if(j!=n)	f[_][i][j+1]=max(f[_][i][j+1],f[_][i][j]);
	}
	int ans=0;
	fz(len,1,n)	for(int i=1,j=len;j<=n;i++,j++){
		fz(k,i,j){
			dp[i][j]=max(dp[i][j],dp[i][k-1]+dp[k+1][j]+f[k][i][j]);
		}
		ans=max(ans,dp[i][j]);
	}
	cout<<ans<<endl;
	return 0;
}
posted @ 2020-05-04 15:35  tzc_wk  阅读(55)  评论(2)    收藏  举报