P1156 垃圾陷阱
题意:给出一只困在井里的动物,给出这只动物目前能够存活时间为10小时
给出n个垃圾(竟然吃辣鸡?)每个辣鸡有投放的时间点,吃这个辣鸡能获得的体力,堆放这个辣鸡能获得的高度
问:假如能逃出这个井,最少花多长时间?
假如不能逃出,最长存活时间为?
思路:首先,我们要将垃圾投放的时间进行从小到大排序
那么,排完序之后,我们肯定能够想到的一步是,第k个垃圾是要用来吃还是用来堆
所以,我们就是要根据这一步来列dp
那么如何列呢,我们要想出一种无后效性的解法
因为垃圾按时间排序,我们就要得出到达某个垃圾时的最优情况,然后在这个垃圾的最优情况下,继续处理下一个垃圾
那么如何才能使前后两个垃圾建立联系呢
自然是从题目给出的信息来找联系,题目中给出了高度,时间,吃垃圾获得体力(显然不可能用这个)
那么能通过时间嘛?不行,时间给出的数据太大,会超时
于是,剩下的只有高度了,题目中高出的高度的上限是100,所以可以想想如何做
所以,开了上帝视角的我,得出这样一个结论:可以开一个第一维记录到了哪个垃圾,第二维记录在这个垃圾的情况下,枚举(0,上限)的高度
那么dp的时候有两种情况
第一种:把垃圾吃掉,想要吃掉垃圾,就要保证能活到投掷这个垃圾的时间点
第二种:堆砌垃圾,要堆砌垃圾,也要活到投掷垃圾的时间点,并且之前的高度不能为负数
然后,假如在投放这个垃圾的时候,已经能够到达顶点,就直接输出投掷这个垃圾的时间即可(表示在这个时间就可以逃出来)
假如一直没有出来,就表明出不来,那么最后再枚举一遍,能存活的最长时间即可
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int maxn=1e3+10; 4 const int inf=0x3f3f3f3f; 5 int f[101][1001]; 6 struct node 7 { 8 int x,t,h; 9 }a[maxn]; 10 int cmp(node a,node b) 11 { 12 return a.x<b.x; 13 } 14 int main() 15 { 16 int n,m; 17 int tmp=10; 18 scanf("%d%d",&n,&m); 19 for(int i=1;i<=m;i++){ 20 scanf("%d%d%d",&a[i].x,&a[i].t,&a[i].h); 21 } 22 sort(a+1,a+m+1,cmp); 23 memset(f,-inf,sizeof(f)); 24 f[0][0]=10; 25 a[0].x=a[0].t=a[0].h=0; 26 int fl=0; 27 for(int i=1;i<=m;i++){ 28 for(int j=0;j<=n;j++){ 29 if(f[i-1][j]-a[i].x+a[i-1].x>=0) { 30 // 把垃圾吃掉,想要吃掉垃圾,就要保证能活到投掷这个垃圾的时间点 31 f[i][j]=max(f[i][j],f[i-1][j]-a[i].x+a[i-1].x+a[i].t); 32 } 33 //堆砌垃圾,要堆砌垃圾,也要活到投掷垃圾的时间点,并且之前的高度不能为负数 34 if (f[i-1][j-a[i].h]-a[i].x+a[i-1].x>=0&&j-a[i].h>=0) { 35 f[i][j]=max(f[i][j],f[i-1][j-a[i].h]-a[i].x+a[i-1].x); 36 if(j==n){ 37 printf("%d\n",a[i].x); 38 fl=1; 39 return 0; 40 } 41 } 42 } 43 } 44 int ans=0; 45 if(!fl){ 46 for(int i=0;i<=m;i++) 47 ans=max(ans,f[i][0]+a[i].x); 48 printf("%d\n",ans); 49 } 50 return 0; 51 }