zoukankan      html  css  js  c++  java
  • [題解]luogu P1156 垃圾陷阱

    前言:[數據刪除]

    來源:題解


    不發題面了

    首先我们来分析题目,“每个垃圾都可以用来吃或堆放”,浓浓的透露出一个背包气息。我们可以类比背包问题的放或不放。于是dp[i][j]dp[i][j]dp[i][j]描述为处理前i个物品的某状态j,那么状态j代表什么呢?

    我们可以继续分析题目并使用排除法

    分析题目,我们需要求的答案是时间,于是很自然而然的想到j描述高度或生命,而dp数组存放时间。很显然,这样状态既不完整,也写不出转移方程。而且dp数组存的是当前状态下最大或最小的价值,似乎也不满足。

    这时候我们发现,有4个值可能成为状态,高度,生命,物品和时间,难道要dp三维的吗?

    再分析题目,每个垃圾都有一个下落的时间,奶牛一定是在垃圾丢下来的时间就处理垃圾的(可以得出这样的最优的),那么物品就可以和时间关联起来了。这时候,我们可以把时间仅仅当作干扰量给剔除了。

    需要注意的是,物品的使用顺序并不是随意的,必须按它们下落的时间顺序来先后处理。(这里排一下序即可)

    那么j代表什么呢?

    一下子我们并不能得出答案。先尝试dp[i][j]代表前i件物品处理后在j血量时达到的最大高度。

    值得一提的是,j血量表示奶牛在暂时不考虑时间时所得到的最大血量

    据说这个是叫离线

    试着写一下它的状态转移方程

    dp[i][j]=max(dp[i−1][j]+trash[i].h,dp[i−1][j+trash[i].c])

    发现这是对的,然而我们再想想,在关于j的一重循环里面,对j的取值我们似乎并不好判断,甚至要枚举很大。

    所以我们再尝试讨论dp[i][j]代表前i件物品处理后在h高度时达到的最大血量。

    状态转移

    dp[i][j]=max(dp[i−1][j]+trash[i].c,dp[i−1][j−trash[i].h])

    发现这样也是对的,而且j枚举起来也比较方便,于是我们选择这种算法。

    重要内容:分析 i,j 代表什么:

    按時間順序排序然後依次轉移,時間數值不固定或者比較大不太好做階段,而且會有很多浪費,所以用前 i 個物品轉移,轉移時在判可行性,處理掉了時間,

    只剩 血量,高度兩維,在考慮怎麼分配,如果用血量做第二維的話數值仍然不確定而且可能很大,於是嘗試交換,對於能否活下來在最後找解的時候在判斷。

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    using namespace std;
    int d,g;
    struct node{
        int t,h,f;
    }e[101];
    int f[101][1001];//i個物品j高度的最大血量(重要 
    bool cmp(node a,node b)
    {
        return a.t<b.t;
    }
    int main()
    {
        scanf("%d%d",&d,&g);
        for(int i=1;i<=g;i++){
            scanf("%d%d%d",&e[i].t,&e[i].f,&e[i].h);
        }
        sort(e+1,e+1+g,cmp);
        f[0][0]=10;//初值 
        for(int i=1;i<=g;i++)
        for(int j=0;j<=d;j++){
            if(f[i-1][j]>=e[i].t)//如果上一個狀態的血量夠用 
            f[i][j]=max(f[i][j],f[i-1][j]+e[i].f);//
            if(j>=e[i].h&&f[i-1][j-e[i].h]>=e[i].t)//如果可以從前一個更低的高度加上這個物品的高度,並且能堅持到下一個垃圾
            f[i][j]=max(f[i][j],f[i-1][j-e[i].h]);//
        }
        int maxh=0,maxt=0,i;
        for(i=1;i<=g;i++){
            for(int j=0;j<=d;j++){
                if(f[i][j]-e[i].t>=0)//一定要判狀態能否使用 
                maxh=max(maxh,j);//更新最高高度 
                maxt=max(maxt,f[i][j]);//每次都要更新最長時間 
            }
            if(maxh>=d)break;
        }
        if(maxh>=d)printf("%d",e[i].t);
        else printf("%d",maxt);
    }
  • 相关阅读:
    (网络编程)基于tcp(粘包问题) udp协议的套接字通信
    (网络编程)理论 原理
    (网络编程) 介绍
    C++开源代码项目汇总
    Facial Landmark Detection
    人脸对齐ASM-AAM-CLM的一些总结
    Ello讲述Haar人脸检测:易懂、很详细、值得围观
    显示形状回归算法(ESR)代码介绍
    百度图像搜索探秘
    人脸特征点检测
  • 原文地址:https://www.cnblogs.com/superminivan/p/10519533.html
Copyright © 2011-2022 走看看