zoukankan      html  css  js  c++  java
  • Luogu P1156 垃圾陷阱 【dp】By cellur925

    题目传送门

    这题...看上去浓浓的背包气息...但是并不好设计状态啊emmm。

    我们考虑可能成为状态的量:高度、血量、时间、物品。看数据范围也猜到应该大概是个二维dp了w。

    正确的状态设计之一:设$f[i][j]$表示用到第$i$个物品,当前高度为$j$的最大血量。为什么用这个状态,因为写转移比较好写==

    每个物品一定在它扔下的那时就被处理的,对于每个物品,每一时间我们有两种决策:堆起来和吃掉。

    • 堆起来:首先在这个时刻奶牛一定是活着的(血量>=0),而且之前的高度一定大于等于0我们要注意检验它是否活着是要把两个相邻物品的时间差减去(这段时间没有进食)。那么便有转移:

       $f[i][j]$=$max${$f[i-1][j-rub[i].h]$-$rub[i].tim$+$rub[i-1].tim$}

    • 吃掉它:同上,这时奶牛也必须活着。

       $f[i][j]$=$max${$f[i-1][j]$-$rub[i].tim$+$rub[i-1].tim$+$rub[i].val$}

    我们的dp部分就结束了。

    之后就是赋初值的细节,开始$f$数组是负无穷的,且有$f[0][0]=10$。

    在处理答案方面,当我们dp时遇到一个与井同高的时刻,我们就可以判断它是否能作为答案。

    如果无解,那么答案就由$f[i][j]$+$rub[i].tim$来寻找最大值。

    Code

     1 #include<cstdio>
     2 #include<algorithm>
     3 #include<cstring>
     4 
     5 using namespace std;
     6 
     7 int well_h,n,ans;
     8 bool flag;
     9 int f[200][500]; 
    10 struct rubbish{
    11     int tim,val,h;
    12 }rub[500];
    13 
    14 bool cmp(rubbish a,rubbish b)
    15 {
    16     return a.tim<b.tim;
    17 }
    18 
    19 int main()
    20 {
    21     scanf("%d%d",&well_h,&n);
    22     for(int i=1;i<=n;i++)
    23         scanf("%d%d%d",&rub[i].tim,&rub[i].val,&rub[i].h);
    24     sort(rub+1,rub+1+n,cmp);
    25     memset(f,128,sizeof(f));
    26     f[0][0]=10;
    27     for(int i=1;i<=n;i++)
    28         for(int j=0;j<=well_h;j++)
    29         {
    30             if(f[i-1][j]-rub[i].tim+rub[i-1].tim>=0)
    31                 f[i][j]=max(f[i][j],f[i-1][j]-rub[i].tim+rub[i-1].tim+rub[i].val);
    32             if(f[i-1][j-rub[i].h]-(rub[i].tim-rub[i-1].tim)>=0&&j-rub[i].h>=0)
    33             {
    34                 f[i][j]=max(f[i][j],f[i-1][j-rub[i].h]-(rub[i].tim-rub[i-1].tim));
    35                 if(j==well_h){printf("%d",rub[i].tim),flag=1;return 0;}
    36             }                
    37         }
    38     if(!flag)
    39         for(int i=0;i<=n;i++)
    40             for(int j=0;j<=well_h;j++)
    41                 ans=max(ans,f[i][j]+rub[i].tim);
    42     printf("%d
    ",ans);
    43     return 0;
    44 }
    View Code

    细节:dp题目注意从0开始枚举的情况。

  • 相关阅读:
    台州 OJ 3847 Mowing the Lawn 线性DP 单调队列
    洛谷 OJ P1417 烹调方案 01背包
    快速幂取模
    台州 OJ 2649 More is better 并查集
    UVa 1640
    UVa 11971
    UVa 10900
    UVa 11346
    UVa 10288
    UVa 1639
  • 原文地址:https://www.cnblogs.com/nopartyfoucaodong/p/9744577.html
Copyright © 2011-2022 走看看