原题链接:https://www.luogu.com.cn/problem/P1156
P1156 垃圾陷阱
题目描述
卡门――农夫约翰极其珍视的一条Holsteins
奶牛――已经落了到“垃圾井”中。“垃圾井”是农夫们扔垃圾的地方,它的深度为D(2≤D≤100)英尺。
卡门想把垃圾堆起来,等到堆得与井同样高时,她就能逃出井外了。另外,卡门可以通过吃一些垃圾来维持自己的生命。
每个垃圾都可以用来吃或堆放,并且堆放垃圾不用花费卡门的时间。
假设卡门预先知道了每个垃圾扔下的时间t(0<t≤1000),以及每个垃圾堆放的高度h(1≤h≤25)和吃进该垃圾能维持生命的时间f(1≤f≤30),要求出卡门最早能逃出井外的时间,假设卡门当前体内有足够持续10小时的能量,如果卡门10小时内没有进食,卡门就将饿死。
输入格式
第一行为2个整数,D和 G(1≤G≤100),G为被投入井的垃圾的数量。
第二到第G+1行每行包括3个整数:T (0 < T <= 1000),表示垃圾被投进井中的时间F(1≤F≤30),表示该垃圾能维持卡门生命的时间;和H(1≤H≤25),该垃圾能垫高的高度。
输出格式
如果卡门可以爬出陷阱,输出一个整表示最早什么时候可以爬出;否则输出卡门最长可以存活多长时间。
输入输出样例
20 4 5 4 9 9 3 2 12 6 10 13 1 1
13
说明/提示
[样例说明]
卡门堆放她收到的第一个垃圾:height=9;
卡门吃掉她收到的第2个垃圾,使她的生命从10小时延伸到13小时;
卡门堆放第3个垃圾,height=19;
卡门堆放第4个垃圾,height=20。
这个题是一个类似背包问题,垃圾的高度看成物重,能增加的生命的长短看成价值,把井的高度看成背包的大小,但和背包不同的是,题目要求至少将这个背包填满,需要对代码进行以下修改
开一个结构体(记录)a[i].t,a[i].f,a[i].h分别代表第i个物体的投入时间,持续生命时间和高度。
设b[j]表示到达高度j时所拥有的最长的生命时间,注意b[0]=10。
那么转态转移应该是if(b[j]>b[j+a[i].h])b[j+a[i].h]=b[j];
如果有一个j+a[i].h>=d,那么就代表走出去了,
如果循环完了还没走出去就应该输出最长存活的时间。
下面是代码:
c/c++:
#include<stdio.h> struct sj{ int t,f,h; }a[1001]; int b[1001]; int d,g; void px(int k,int s){ int i,j,mid; struct sj p; i=k;j=s; mid=a[(k+s)/2].t; do{ while(a[i].t<mid)i++; while(a[j].t>mid)j--; if(i<=j){ p=a[i]; a[i]=a[j]; a[j]=p; i++;j--;} }while(i<=j); if(i<s)px(i,s); if(k<j)px(k,j); } int main(){ scanf("%d%d",&d,&g); for(int i=1;i<=g;i++)scanf("%d%d%d",&a[i].t,&a[i].f,&a[i].h); px(1,g); b[0]=10; for(int i=1;i<=g;i++)for(int j=d;j>=0;j--) if(b[j]>=a[i].t){ if(j+a[i].h>=d){printf("%d",a[i].t);return 0;}; if(b[j]>b[j+a[i].h])b[j+a[i].h]=b[j]; b[j]+=a[i].f; } printf("%d",b[0]); return 0; }
pascal:
type sj=record t:integer; f:integer; h:integer; end; var a:array[0..1000]of sj; b:array[0..1000]of integer; d:integer; g:integer; procedure px(k,s:integer); var i:integer; j:integer; mid:integer; p:sj; begin i:=k;j:=s; mid:=a[(k+s) div 2 ].t; while i<=j do begin while a[i].t<mid do i:=i+1; while a[j].t>mid do j:=j-1; if i<=j then begin p:=a[i]; a[i]:=a[j]; a[j]:=p; i:=i+1; j:=j-1; end; end; if i<s then px(i,s); if k<j then px(k,j); end; var i:integer; j:integer; begin readln(d,g); for i:=1 to g do readln(a[i].t,a[i].f,a[i].h); px(1,g); b[0]:=10; for i:=1 to g do for j:=d downto 0 do if b[j]>=a[i].t then begin if j+a[i].h>=d then begin writeln(a[i].t);exit(); end; if b[j]>b[j+a[i].h] then b[j+a[i].h]:=b[j]; b[j]:=b[j]+a[i].f; end; writeln(b[0]); end.