[洛谷P1156][codevs1684]垃圾陷阱

题目大意:一头奶牛掉进了深度为d的坑里,现在有g个垃圾在特定时刻ti扔进来。奶牛可以吃垃圾以获得体力,吃第i个垃圾能获得mi的体力,也可以堆放垃圾以逃生,第i个垃圾高度为hi。当高度≥d时奶牛成功逃生。但当体力值小于0时逃生失败(每一个单位时间耗费一点体力)。

现在奶牛初始体力值为10,问:如果能逃生,最短什么时候;如果不能,最长能活多久?

解题思路:动态规划。

设dp[i][j]表示到第i个垃圾扔下来的时候,已经堆到j的高度时,奶牛剩余的最大体力。则

$dp[i][j]=max(dp[i][j-h[i]]-(t[i]-t[i-1])(当dp[i][j-h[i]]-(t[i]-t[i-1])geq 0时),dp[i][j]-(t[i]-t[i-1])+m[i](当dp[i][j]-(t[i]-t[i-1])geq 0时))$。

每次判断dp[i][d]是否≥0,如果是,则t[i]就是答案。

如果dp完后还未得出答案,说明无法逃生,则贪心求出能活的最长时间即可(即扔进来的垃圾全吃了,到饿死为止)。

注意按照投入时刻进行排序。

时间复杂度$O(dg)$。

C++ Code:

#include<cstdio>
#include<cstdarg>
#include<cctype>
#include<algorithm>
#include<cstring>
using namespace std;
int d,n,dp[102][25005];
struct brush{
	int t,m,h;
	bool operator <(const brush& rhs)const{return t<rhs.t;}
}a[102];
inline int readint(){
	char c=getchar();
	bool b=false;
	for(;!isdigit(c);c=getchar())b=c=='-';
	int d=0;
	for(;isdigit(c);c=getchar())
	d=(d<<3)+(d<<1)+(c^'0');
	return b?-d:d;
}
inline void read(int cnt,...){
    va_list arg_ptr;
    va_start(arg_ptr,cnt);
    for(int i=0;i<cnt;++i){
        int* p=va_arg(arg_ptr,int*);
        *p=readint();
    }
}
int main(){
	read(2,&d,&n);
	for(int i=1;i<=n;++i)read(3,&a[i].t,&a[i].m,&a[i].h);
	sort(a+1,a+n+1);
	memset(dp,170,sizeof dp);
	dp[0][0]=10;
	a[0].t=0;
	for(int i=1;i<=n;++i){
		int tcha=a[i].t-a[i-1].t;
		for(int j=0;j<=d;++j){
			if(dp[i-1][j]-tcha>=0)
			dp[i][j]=max(dp[i][j],dp[i-1][j]-tcha+a[i].m);
			if(j>=a[i].h)
			if(dp[i-1][j-a[i].h]-tcha>=0)
			dp[i][j]=max(dp[i][j],dp[i-1][j-a[i].h]-tcha);
		}
		if(dp[i][d]>=0){
			printf("%d
",a[i].t);
			return 0;
		}
	}
	int hp=10;
	for(int i=1;i<=n;++i){
		if(hp>=a[i].t)hp+=a[i].m;else{
			printf("%d
",hp);
			return 0;
		}
	}
	printf("%d
",hp);
	return 0;
}
原文地址:https://www.cnblogs.com/Mrsrz/p/7736261.html