P1156 垃圾陷阱

Posted planche

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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),该垃圾能垫高的高度。

 

输出格式:

 

如果卡门可以爬出陷阱,输出一个整表示最早什么时候可以爬出;否则输出卡门最长可以存活多长时间。

 

输入输出样例

输入样例#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。

//二维
#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;
}

 

以上是关于P1156 垃圾陷阱的主要内容,如果未能解决你的问题,请参考以下文章

[luogu]P1156 垃圾陷阱[DP]

洛谷 P1156 垃圾陷阱

Luogu P1156 垃圾陷阱

P1156 垃圾陷阱

P1156 垃圾陷阱

洛谷 P1156 垃圾陷阱