题解 P1156 【垃圾陷阱】
I_AM_HelloWord · · 题解
应该看得出就是一个背包吧!把垃圾的高度看成物重,能增加的生命的长短看成价值,
然后把井的高度看成包的大小,要求必须把包填满(或爆)能取得的最小价值【手动滑稽】。
直接搞一个背包:
设dp[i][j]表示前i个垃圾(注意一定要先按垃圾出现时间排序好),到达高度j时所拥有的最长的生命时间。
那么dp[i][j]=max(dp[i][j],dp[i-1][j]+a[i].v-(a[i].t-a[i-1].t))(吃,不填)
dp[i][j]=max(dp[i][j],dp[i-1][j-a[i].h]-(a[i].t-a[i-1].t))(不吃,填)
如果有一个dp[i][j]>=0且j+a[i].h>=D,那么就走出去了,
不然就是在dp[i][0]+a[i].t中取个最大值就好了。
至于刷表法,还是填表法,就看个人喜好了。
搞一个滚动数组优化一下空间(其实没必要,弄不好还搞错了)。
参考代码:
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int INF=0x3f3f3f3f;
const int M=1010;
struct Rubbish{
int t,v,h;
bool operator < (const Rubbish &rhs) const {
return t<rhs.t;
}
}a[M];
int dp[2][M],n,m;
int read(){
int x=0,f=1;char ch=getchar();
while (ch<'0' || ch>'9'){if (ch=='-')f=-1;ch=getchar();}
while ('0'<=ch && ch<='9'){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
return x*f;
}
int main(){
m=read(),n=read();
for (int i=1;i<=n;i++)
a[i].t=read(),a[i].v=read(),a[i].h=read();
sort(a+1,a+n+1);
memset(dp,~0x3f,sizeof(dp));
dp[0][0]=10;a[0].t=0;
int res=-INF;
for (int i=1;i<=n;i++){
int cur=i&1,pre=cur^1;
memset(dp[cur],~0x3f,sizeof(dp[cur]));
for (int j=m;j>=0;j--){
if (dp[pre][j]<a[i].t-a[i-1].t)continue;
if (j+a[i].h>=m){
printf("%d",a[i].t);
return 0;
}
dp[cur][j+a[i].h]=max(dp[cur][j+a[i].h],dp[pre][j]-(a[i].t-a[i-1].t));
dp[cur][j]=max(dp[pre][j]+a[i].v-(a[i].t-a[i-1].t),dp[cur][j]);
}
res=max(res,dp[cur][0]+a[i].t);
}
printf("%d",res);
return 0;
}