题解 P1156 【垃圾陷阱】

· · 题解

根据这道题的无后效性 ,以及题目的标签显然是道dp的题目。那么就应该看出是一个背包问题吧。

一维背包的模板+优化:

for(int i=1; i<=m; i++) { // weight

    for(int j=n; j>=w[i]; j--) { // things;

        dp[j]=max(dp[j],dp[j-w[i]]+v[i]);

    }

把垃圾的高度看成物重(weight),能增加的生命的长短看成价值(things)。(不然不好做,写的时候多尝试)

然后把井的深度看成包的大小(n),垃圾的个数为物品数量(m)。(与上一一对应,但还需改动)

要求必须把包填满,所能取得的最小价值。

用一个结构体定义垃圾的 t(表示垃圾被投进井中的时间),f(表示该垃圾能维持卡门生命的时间),h(该垃圾能垫高的高度)。

struct per {
    int t;
    int f;
    int h;
} r[105];//rubish-

然后以时间排序(由题意,显然)

bool cmp(per a,per b) {
    return a.t<b.t;
}

与

sort(r+1,r+g+1,cmp);                    

以上都是预备工作。

focus on !!!!!

核心的状态转移方程 :

别忘了,要加上判断

if(dp[height]>=r[j].t)  //在这个时间,牛牛还没gg(之前已经用时间排过序了,时间递增)

来个完整的code:

#include<bits/stdc++.h>
#define ll long long
using namespace std;
int d,g,k=1,ans;
struct per {
    int t;
    int f;
    int h;
} r[105];
int dp[2505];
bool cmp(per a,per b) {
    return a.t<b.t;
}
int main() {
    cin>>d>>g;
    for(int j=1; j<=g; j++)
        cin>>r[j].t>>r[j].f>>r[j].h;
    sort(r+1,r+g+1,cmp);

    ————————————————————————
    ans=10;//这一段是为了判断最大活了多久,可以与下面和在一起,但循环展开更快(手动滑稽)。
    for(int j=1; j<=g; j++)
        if(ans>=r[j].t) ans+=r[j].f;//很显然的算法

    ————————————————————————    
    dp[0]=10;//刚开始的初始化

    for(int j=1; j<=g; j++) 
        for(int height=d-r[j].h; height>=0; height--) //记得倒过来,他会反着刷过来,实在不会换2维数组也可以
            if(dp[height]>=r[j].t) {
                dp[height+r[j].h]=max(dp[height+r[j].h],dp[height]);
                if(dp[d]>0) {//最大高度的生命值不为0了,就说明,牛牛已经到了井的顶端
                    printf("%d ",r[j].t);
                    return 0;
                }
                dp[height]+=r[j].f;
            }
    printf("%d",ans);//到不了,输出活最久的时间
    return 0;
}

don't copy please

个人感觉简单易懂 ,还很短,希望有帮助。

φ(>ω<) 求过加点顶 (>ω・ )ノ