题解:P1156 垃圾陷阱

P1156 垃圾陷阱#

思路:#

很显然这是一道动态规划,且每个物品有两种选择:用作增加生命或高度。

增加高度会损失一定的生命,反之同理,是不是很像背包问题?确实是它的变形。
考虑设 \(f[i][j]\) 表示到第 \(i\) 个物品,生命值为 \(j\) 时所到达的最大高度。
那么我们考虑转移,显然对于物品 \(i\) 用作增加高度有:

\(f[i][j]=max(f[i-1][j]+h[i])\)

用作增加生命有:

\(f[i][j]=max(f[i-1][j-f[i]])\)

坑点:#

  1. 注意转移调用变量时奶牛是否还存活。

  2. 给出的垃圾掉落时间的 \(t\) 数组不保证单调递增,需要排序。

代码:#

#include<bits/stdc++.h>
#define ll long long
using namespace std;
struct node {
	ll t, f, h, sum;
	bool operator < (node &a) {return t<a.t;}
}a[1005];
ll h, n;
ll f[105][100005]; //f[i][j]表示前i个垃圾生命值为j时能达到的最高高度 
int main() {
	cin >> h >> n;
	for(int i=1; i<=n; i++) cin >> a[i].t >> a[i].f >> a[i].h; //t表示投放时间,f表示增加的生命值,h表示垫高高度 
	sort(a+1, a+n+1); //注意给出的时间不递增 
	a[0].sum=10;
	for(int i=1; i<=n; i++) a[i].sum=a[i-1].sum+a[i].f; //a[i].sum表示到i能达到的最大高度 
	memset(f, -0x3f, sizeof(f));
	f[0][10]=0; //初始化 
	for(int i=1; i<=n; i++) {
		if(a[i].t>a[i-1].sum) { //就算前面的所有垃圾都吃也坚持不到这个垃圾,输出最大高度 
			cout << a[i-1].sum;
			exit(0);
		}
		for(int j=a[i].t; j<=a[i].sum; j++) { //j从a[i].t开始枚举保证能存活到当前垃圾投放,且最大高度不大于a[i].sum 
			f[i][j]=max(f[i][j], f[i-1][j]+a[i].h); //这个垃圾用来垫高高度 
			//接下来考虑这个垃圾用来增加生命值,那么j-a[i].f>=0且j-a[i].f>=a[i].t(保证能活到当前垃圾时间)
			if(j-a[i].f>=0&&j-a[i].f>=a[i].t) f[i][j]=max(f[i][j], f[i-1][j-a[i].f]);
			if(f[i][j]>=h) { //如果不小于h说明到i时就出去了,输出a[i].t
				cout << a[i].t;
				exit(0);
			}
		}
	}
	cout << a[n].sum; //能运行到这里说明所有最大高度不足以出洞 
	return 0;
}

作者:Anins

出处:https://www.cnblogs.com/anins/p/18565834

版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。

posted @   Anins  阅读(17)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
more_horiz
keyboard_arrow_up dark_mode palette
选择主题
menu
点击右上角即可分享
微信分享提示