洛谷 P1156 垃圾陷阱 记忆化搜索
题目描述
卡门――农夫约翰极其珍视的一条Holsteins
奶牛――已经落了到“垃圾井”中。“垃圾井”是农夫们扔垃圾的地方,它的深度为D(2 \le D \le 100)D(2≤D≤100)英尺。
卡门想把垃圾堆起来,等到堆得与井同样高时,她就能逃出井外了。另外,卡门可以通过吃一些垃圾来维持自己的生命。
每个垃圾都可以用来吃或堆放,并且堆放垃圾不用花费卡门的时间。
假设卡门预先知道了每个垃圾扔下的时间t(0< t \le 1000)t(0<t≤1000),以及每个垃圾堆放的高度h(1 \le h \le 25h(1≤h≤25)和吃进该垃圾能维持生命的时间f(1 \le f \le 30)f(1≤f≤30),要求出卡门最早能逃出井外的时间,假设卡门当前体内有足够持续1010小时的能量,如果卡门1010小时内没有进食,卡门就将饿死。
输入输出格式
输入格式:
第一行为22个整数,DD和 G (1 \le G \le 100)G(1≤G≤100),GG为被投入井的垃圾的数量。
第二到第G+1G+1行每行包括33个整数:T (0 < T <= 1000)T(0<T<=1000),表示垃圾被投进井中的时间;F (1 \le F \le 30)F(1≤F≤30),表示该垃圾能维持卡门生命的时间;和 H (1 \le H \le 25)H(1≤H≤25),该垃圾能垫高的高度。
输出格式:
如果卡门可以爬出陷阱,输出一个整表示最早什么时候可以爬出;否则输出卡门最长可以存活多长时间。
输入输出样例
说明
[样例说明]
卡门堆放她收到的第一个垃圾:height=9height=9;
卡门吃掉她收到的第22个垃圾,使她的生命从1010小时延伸到1313小时;
卡门堆放第33个垃圾,height=19height=19;
卡门堆放第44个垃圾,height=20height=20。
又是一道奶牛题。。。。
用记忆化搜索写的,一开始保存的是最大高度,结果WA之后才发现要输出的是时间。。(不仔细读题+自信不过样例的后果)原先用f[i][j]表示第i个垃圾j生命值时能到达的最大高度,要保存时间是没辙的,于是考虑增加
一维,用f[i][j][k]表示第i个垃圾j生命值k高度时最小的时间,对于每一个垃圾有吃和堆两种选择,这样方程就出来了
f[n][hp][h]=min(dfs(n+1,hp+a[n].life,h),dfs(n+1,hp,h+a[n].high));
这题还有一个坑点是,别看样例给你的时间是有序的,真正的数据是打乱顺序的。。。一定要先排序,不然死都不知道怎么死的
完整代码
#include<bits/stdc++.h> using namespace std; struct node{ int high,life,time; }a[105]; int d,m,f[505][505][505]; bool cmp(node i,node j) { return i.time<j.time; } int dfs(int n,int hp,int h) { if(n>m||hp<a[n].time)return 0x7fffffff;//这里也有坑点,当前牛的生命值为0时也是可以操作的。。。一开始写了<=调了半天 if(h+a[n].high>=d)return a[n].time; if(f[n][hp][h])return f[n][hp][h]; return f[n][hp][h]=min(dfs(n+1,hp+a[n].life,h),dfs(n+1,hp,h+a[n].high)); } int main() { scanf("%d%d",&d,&m); for(int i=1;i<=m;i++) scanf("%d%d%d",&a[i].time,&a[i].life,&a[i].high); sort(a+1,a+m+1,cmp);//排序!排序!排序! if(dfs(1,10,0)!=0x7fffffff)cout<<f[1][10][0];//如果不会挂掉直接输出 else{//会挂掉的话 int ans=10; for(int i=1;i<=m;i++)//挨个枚举,直到挂掉的时候为止 { if(ans<a[i].time)break; ans+=a[i].life; } cout<<ans; } //cout<<dfs(1,10,0); return 0; }
参考大佬@真实姓名 的题解