题目描述
卡门――农夫约翰极其珍视的一条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),该垃圾能垫高的高度。
输出格式:
如果卡门可以爬出陷阱,输出一个整表示最早什么时候可以爬出;否则输出卡门最长可以存活多长时间。
输入输出样例
输入样例#1:
20 4 5 4 9 9 3 2 12 6 10 13 1 1
输出样例#1:
13
说明
[样例说明]
卡门堆放她收到的第一个垃圾:height=9;
卡门吃掉她收到的第二个垃圾,使她的生命从10小时延伸到13小时;
卡门堆放第3个垃圾,height=19;
卡门堆放第4个垃圾,height=20。
首先,考虑到节约空间并且便于转移,我们用dp[i][j]表示到了第i个垃圾的时候,高度为j,生命值最大是多少。那么很显然状态转移方程就应该有2种情况:1、吃了当前块。2、没有吃当前块。转移的条件就应该是奶牛能活过i、i-1两个物品间的间隔。注意到我们要对j为0~井深的所有状态进行转移。另外,这道题刷表比填表好写的多,建议刷表。
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int maxn = 2e3 + 5; int dp[maxn][105], n, d, ans; struct item { int food, h, time; bool operator <(const item &a) const {return time < a.time;} }items[105]; signed main() { scanf("%d%d", &d, &n); memset(dp, 0xc0, sizeof(dp)); for(register int i = 1; i <= n; ++i) scanf("%d%d%d", &items[i].time, &items[i].food, &items[i].h); sort(items + 1, items + 1 + n); dp[0][0] = 10; for(register int i = 1; i <= n; ++i) { for(register int j = 0; j <= d; ++j) { if(dp[i - 1][j] < items[i].time - items[i - 1].time) continue; if(j + items[i].h >= d) { printf("%d", items[i].time); return 0; } if(dp[i][j] < dp[i - 1][j] + items[i].food - (items[i].time - items[i - 1].time)) dp[i][j] = dp[i - 1][j] + items[i].food - (items[i].time - items[i - 1].time); if(dp[i][j + items[i].h] < dp[i - 1][j] - (items[i].time - items[i - 1].time)) dp[i][j + items[i].h] = dp[i - 1][j] - (items[i].time - items[i - 1].time); } if(ans < dp[i][0] + items[i].time) ans = dp[i][0] + items[i].time; } printf("%d", ans); return 0; }
没有帐号? 立即注册