题目描述
卡门――农夫约翰极其珍视的一条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),该垃圾能垫高的高度。
输出格式:
如果卡门可以爬出陷阱,输出一个整表示最早什么时候可以爬出;否则输出卡门最长可以存活多长时间。
输入输出样例
说明
[样例说明]
卡门堆放她收到的第一个垃圾:height=9;
卡门吃掉她收到的第二个垃圾,使她的生命从10小时延伸到13小时;
卡门堆放第3个垃圾,height=19;
卡门堆放第4个垃圾,height=20。
//二维 #include<bits/stdc++.h> using namespace std; #define maxn 2600 #define inf 0x3f3f3f3f struct node { int t,w,v; } a[maxn]; bool cmp(node a,node b) { return a.t<b.t; } int dp[maxn][maxn]; //dp[i][j]:代表前i个垃圾,高度为j,能得到的最大生命值 //dp[i][j]=max(dp[i][j],dp[i-1][j-a[i].w]-(a[i].t-a[i-1].t),dp[i-1][j]-(a[i].t-a[i-1].t)+a[i].v); int W,n; int H=0; int main() { cin>>W>>n; for(int i=1; i<=n; i++) { cin>>a[i].t>>a[i].v>>a[i].w; H+=a[i].w; } sort(a+1,a+1+n,cmp);//一定要时间排序 for (int i=0; i<=n; i++) for (int j=0; j<=H; j++) dp[i][j]=-inf; //千万记住,不能这么写 fill(dp[0],dp[0]+(n+1)*(H+1)+1,-inf); //fill函数会先把每个位置都填满才跨越下一级 dp[0][0]=10; for(int i=1; i<=n; i++) for(int j=0; j<=H; j++) { //因为条件不同的关系,需要分两次进行max更新 if(dp[i-1][j]-a[i].t+a[i-1].t>=0) dp[i][j]=max(dp[i][j],dp[i-1][j]-a[i].t+a[i-1].t+a[i].v); if(j-a[i].w>=0) dp[i][j]=max(dp[i][j],dp[i-1][j-a[i].w]-a[i].t+a[i-1].t); //提前跳出&&不死 if(j>=W&&dp[i][j]>=0) { cout<<a[i].t; return 0; } } //这里血量sum一定要和a[i].t时刻这两者区分开来,他妈的 int sum=10; for(int i=1; i<=n; i++) { if(sum-a[i].t+a[i-1].t<0) { cout<<a[i-1].t+sum; return 0; } sum=sum-a[i].t+a[i-1].t+a[i].v; } cout<<a[n].t+sum; return 0; }
//一维 #include<bits/stdc++.h> using namespace std; #define maxn 2600 #define inf 0x3f3f3f3f struct node{ int t,w,v; }p[maxn]; int W,n; int dp[maxn]; bool cmp(node a,node b){ return a.t<b.t; } int main() { cin>>W>>n; for(int i=1;i<=n;i++) cin>>p[i].t>>p[i].v>>p[i].w; sort(p+1,p+1+n,cmp); dp[0]=10; //dp[j]代表此时遍历((目标对象))为第i堆垃圾,且((冲击目标))为高度为j时,总计能存活的最长时间 //因为我是要讨论第i,j,所以i,j是还没有遍历到的,属于目标对象 for(int i=1;i<=n;i++) for(int j=W;j>=0;j--) if(dp[j]>=p[i].t){ if(j+p[i].w>=W){ cout<<p[i].t; return 0; } //加高 dp[j+p[i].w]=max(dp[j+p[i].w],dp[j]); //加血 dp[j]+=p[i].v; } cout<<dp[0];//这里的dp[0]的含义是反正肯定会死,所以把所有的选择全部设为吃垃圾,都不用来加高,所有高度恒为0 return 0; }