【USACO19】Greedy Pie Eaters P
Cry_For_theMoon · · 题解
传送门
这道水题WA了3次才发现
设 蒟蒻WA了三次就是输出了 f(1,m))
我们知道,
那么怎么确定吃掉第
如果你使用这两个方程转移,你会发现根本不需要判断是不是会出界!,因为不合法状况一定不会RE且为0,符合不合法状况的理想的值。
然后你会发现
代码里提供了一种区间DP的不易出错的写法:既然区间DP的转移通常是小区间转移大区间,可以最外层枚举长度,第二层枚举起点,此时终点易得,第三层枚举断点。这个套路就不需要记 真是为OI赛制量身定做的写法QwQ)
//USACO2019,Platinum
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAXN=310,MAXM=90010;
int f[MAXN][MAXN],g[MAXN][MAXN][MAXN];
int w[MAXM],l[MAXM],r[MAXM];
int n,m;
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++){
scanf("%d%d%d",&w[i],&l[i],&r[i]);
for(int j=l[i];j<=r[i];j++){
g[l[i]][r[i]][j] = w[i];
}
}
for(int len=1;len<=n;len++){
for(int i=1;i+len-1<=n;i++){
int j = i+len-1;
for(int k=i;k<=j;k++){
g[i][j][k] = max(g[i][j][k],max(g[i+1][j][k],g[i][j-1][k]));
}
}
}
for(int len = 1;len<=n;len++){
for(int i=1;i+len-1<=n;i++){
int j = i+len-1;
for(int k=i;k<j;k++){
f[i][j] = max(f[i][j],f[i][k]+f[k+1][j]);
}
for(int k=i;k<=j;k++){
f[i][j] = max(f[i][j],g[i][j][k] + f[i][k-1] + f[k+1][j]);
}
}
}
printf("%d\n",f[1][n]);
return 0;
}