这真是一道好题目

学到了很多

一开始感觉吃或者不吃会有后效性

然后看到洛谷的题解,直接把这个有后效性的部分当作dp的维度和值

因为这个垃圾可以堆或者不堆,所以这个很像01背包,

但是加了非常多的限制条件,是一个升级版的01背包

记住思考01背包问题的时候,要思考i那一维度,最后再考虑要不要用滚动数组

否则会增加思维难度

这里有几个量,是高度,生命,时间

因为时间是固定的,所以可以不理他

然后就是高度和生命谁作维度谁做值

生命没有具体的范围,不好枚举,

所以我们就拿高度为维度,来枚举,范围最大为题目给的d

f[i][j]为前i个物品高度为j的最大生命值

则f[i][j] = max(f[i-1][j] + a[i].v)  这是吃垃圾

  f[i][j] = max(f[i-1][j-a[i].h])    这是堆垃圾

注意前提是之前的状态是存在的,即不死。

如果有存在状态是j >= m(题目给的高度),那么就可以输出当前垃圾的时间

如果没有,就输出max(f[i][0])

然后这里有个非常非常牛逼的技巧,可以简化很多
这里的生命值是忽略时间导致生命值的减少的。(洛谷上说这是离线算法)
但是比较的时候就要和当前时间比。

如果这里生命值是算上时间导致的生命值减少,

那么比较的时候显然和0比。

那么这两者只是比较上有差别,但是如果要计算

时间的减少的话代码会多一些。

01背包一样,可以用滚动数组,把i这一维省掉

然后可以用填表法或者刷表法

其实我自己的思维习惯是填表法,即从前面

的状态推到当前状态。

但是对于这道题,显然刷表法更方便,即用现在的状态

推后来的状态

因为这里有个判断当前状态存不存在的问题

填表法的话因为从两个状态过来,所以要判断两次

但是如果是刷表法的话,只用判断当前的状态是否存在,

后来的状态等到枚举后来的状态自然会判断,只用判断一次。

大家可以自行体会一下两种方法。

填表法

#include<cstdio>
#include<algorithm>
#include<cstring>
#define REP(i, a, b) for(int i = (a); i < (b); i++)
using namespace std; const int MAXN = 1123;
int f[MAXN], n, m;
struct node
{
int t, v, h;
void read() { scanf("%d%d%d", &t, &v, &h); }
bool operator < (const node& rhs) const
{
return t < rhs.t;
}
}a[MAXN]; int main()
{
scanf("%d%d", &m, &n);
REP(i, 1, n + 1) a[i].read();
sort(a + 1, a + n + 1); f[0] = 10;
a[0].t = 0;
REP(i, 1, n + 1)
for(int j = m; j >= 0; j--)
{
if(f[j] >= a[i].t)
f[j] = max(f[j], f[j] + a[i].v);
if(j >= a[i].h && f[j-a[i].h] >= a[i].t)
f[j] = max(f[j], f[j-a[i].h]); if(f[j] >= a[i].t && j == m)
{
printf("%d\n", a[i].t);
return 0;
}
}
printf("%d\n", f[0]); return 0;
}

刷表法

#include<cstdio>
#include<algorithm>
#include<cstring>
#define REP(i, a, b) for(int i = (a); i < (b); i++)
using namespace std; const int MAXN = 1123;
int f[MAXN], n, m;
struct node
{
int t, v, h;
void read() { scanf("%d%d%d", &t, &v, &h); }
bool operator < (const node& rhs) const
{
return t < rhs.t;
}
}a[MAXN]; int main()
{
scanf("%d%d", &m, &n);
REP(i, 1, n + 1) a[i].read();
sort(a + 1, a + n + 1); f[0] = 10;
a[0].t = 0;
REP(i, 1, n + 1)
for(int j = m; j >= 0; j--)
if(f[j] >= a[i].t)
{
if(j + a[i].h >= m)
{
printf("%d\n", a[i].t);
return 0;
}
f[j+a[i].h] = max(f[j+a[i].h], f[j]);
f[j] += a[i].v;
}
printf("%d\n", f[0]); return 0;
}

总结

(1)01背包的思考方法

(2)状态的离线设计方法

(3)填表法与刷表法的比较

洛谷 P1156 垃圾陷阱 (01背包拓展)(好题!!)的更多相关文章

  1. 洛谷 P1156 垃圾陷阱

    2016-05-31 09:54:03 题目链接 :洛谷 P1156 垃圾陷阱 题目大意: 奶牛掉坑里了,给定坑的深度和方块的个数,每个方块都可以垫脚或者吃掉维持生命(初始为10) 若可以出来,求奶牛 ...

  2. 洛谷——P1156 垃圾陷阱

    P1156 垃圾陷阱 题目描述 卡门――农夫约翰极其珍视的一条Holsteins奶牛――已经落了到“垃圾井”中.“垃圾井”是农夫们扔垃圾的地方,它的深度为D(2 \le D \le 100)D(2≤D ...

  3. 洛谷P1156 垃圾陷阱 dp

    正解:dp 解题报告: 这儿是传送门! 话说最近怎么神仙们都开始狂刷dp,,,感觉今天写了好多dp的题解的样子?(也就三四道其实× 然后这题,首先看到要么吃要么堆起来就会想到01背包趴?然后就考虑设方 ...

  4. 洛谷 P1156 垃圾陷阱 题解

    题目传送门 dp+排序+01背包 就完事了??? 貌似就是这样的 代码: //dp 排序 01背包 #include<iostream> #include<cstdio> #i ...

  5. P1060 开心的金明(洛谷,动态规划递推,01背包轻微变形题)

    题目链接:P1060 开心的金明 基本思路: 基本上和01背包原题一样,不同点在于这里要的是最大重要度*价格总和,我们之前原题是 f[j]=max(f[j],f[j-v[i]]+p[i]); 那么这里 ...

  6. 洛谷P1156 垃圾陷阱[背包DP]

    题目描述 卡门――农夫约翰极其珍视的一条Holsteins奶牛――已经落了到“垃圾井”中.“垃圾井”是农夫们扔垃圾的地方,它的深度为D(2<=D<=100)英尺. 卡门想把垃圾堆起来,等到 ...

  7. 洛谷P1156 垃圾陷阱【线性dp】

    题目:https://www.luogu.org/problemnew/show/P1156 题意: 每一个垃圾投放时间是t,可以堆的高度是h,如果吃掉可以增加的生命值是f. 给定g个垃圾,初始生命值 ...

  8. 洛谷P1156 垃圾陷阱

    动规仍然是难关啊 题目描述 卡门――农夫约翰极其珍视的一条Holsteins奶牛――已经落了到“垃圾井”中.“垃圾井”是农夫们扔垃圾的地方,它的深度为D(2<=D<=100)英尺. 卡门想 ...

  9. 洛谷 P1156 垃圾陷阱 谈论剪枝,非满分

    这是一个91分的非dp代码(是我太弱) 剪枝八五个(实际上根本没那么多,主要是上课装逼,没想到他们dp水过去了),不过我的思路与dp不同: 1.层数到达i+1,return 这个必须有 2.当前剩余生 ...

随机推荐

  1. java高级——生产者消费者问题

    多线程是一个很重要的应用,本节讲述多线程中同步问题 public class ThreadDemo { public static void main(String[] args) { Resourc ...

  2. MyBatis数据持久化(七)多表连接查询

    本节继续以多表连接查询的案例介绍使用resultMap的好处,对于两张以上的表进行关联查询,当我们有选择的从不同表查询所需字段时,使用resultMap是相当方便的.例如我们有两张表,分别为用户表Us ...

  3. windows 路由

    route ? 查看帮助 route print 查看路由表 添加一条路由: route add 10.10.10.0 mask 255.255.255.0  192.168.1.1 #到达10.10 ...

  4. C++12.1.4 类的前向声明、不完全类型类

    只声明却没有定义的类称为—————–不完全类型,不完全类型不能定义该类型的对象,只能用于定义指向该类型的指针及引用,或者用于声明(不是定义)使用该类型作为形参类型或返回类型的函数. 在创建类的对象之前 ...

  5. Python的那些坑--------括号篇

    在Python中遇见了带不带括号的问题,我目前的是这三种,有问题请指出.如果有其他的,我后续会更新 一  函数带不带括号: def a(x): return x print(a) #不带括号调用的结果 ...

  6. 紫书 习题 11-10 UVa 12264 (二分答案+最大流)

    书上写的是UVa 12011, 实际上是 12264 参考了https://blog.csdn.net/xl2015190026/article/details/51902823 这道题就是求出一种最 ...

  7. WinCE的C#中使用StreamReader 来读取TXT文档,读取文本文档。

    using System.IO; private void button1_Click(object sender, EventArgs e) { string strFilePath = " ...

  8. MySQl Study学习之--MySQl二进制日志管理

    MySQl Study学习之--MySQl二进制日志管理 MySQL二进制日志(Binary Log)   a.它包括的内容及作用例如以下:     包括了全部更新了数据或者已经潜在更新了数据(比方没 ...

  9. jsp布局中关于&lt;iframe&gt;标签的使用

    iframe 元素会创建包括另外一个文档的内联框架(即行内框架). 注意:在 HTML 4.1 Strict DTD 和 XHTML 1.0 Strict DTD 中,不支持 iframe 元素. & ...

  10. hadoop 多文件夹输入,map到reduce怎样排序

    使用MultipleInputs.addInputPath 对多个路径输入 如今如果有三个文件夹,并使用了三个mapper去处理, 经过map处理后,输出的结果会依据key 进行join, 假设使用T ...