P5851 [USACO19DEC] Greedy Pie Eaters P
n,m較小,同時又是區(qū)間問題,可以考慮區(qū)間dp。
設定\(f[i][j]\)為只在i ~ j 范圍內操作的最大貢獻,為了將操作表示出來可以設g[k][i][j]為在i ~ j 內操作一次的包括k點最大貢獻。
通過這些可以推出:
\(f[i][j]=max_{k=i}^jf[i][k-1]+f[k+1][j]+g[k][i][j]\),這樣一來兩邊的操作也不會沖突,又可以保證一定可以一次操作因為中間一定留了一個k點。
反過來看g,也就是又一次區(qū)間dp的操作罷了,對于一頭牛的\(l_i,r_i\),把\(x\in[l_i,r_i]\)的\(g[x][l_i][r_i]=w_i\)就是初始化,然后只需要最大貢獻,于是取最大值,\(g[k][i][j]=max(g[k][i+1][j],g[k][i][j-1])\)。
#include<algorithm>
#include<stdio.h>
#define ll long long
using namespace std;
int n,m;
ll g[305][305][305];
ll f[305][305];
int main() {
// freopen("P5851.in","r",stdin);
// freopen("P5851.out","w",stdout);
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++) {
ll w;int l,r; scanf("%lld%d%d",&w,&l,&r);
for(int k=l;k<=r;k++) g[k][l][r]=max(g[k][l][r],w);
}
for(int len=1;len<=n;len++) {
for(int l=1;l+len-1<=n;l++) {
int r=l+len-1;
for(int k=l;k<=r;k++) {
g[k][l][r]=max(g[k][l][r],max(g[k][l+1][r],g[k][l][r-1]));
}
}
}
for(int len=1;len<=n;len++) {
for(int l=1;l+len-1<=n;l++) {
int r=l+len-1;
for(int k=l;k<=r;k++) {
f[l][r]=max(f[l][r],f[l][k-1]+g[k][l][r]+f[k+1][r]);
}
}
}
printf("%lld",f[1][n]);
return 0;
}

浙公網安備 33010602011771號