洛谷 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;
}