zoukankan      html  css  js  c++  java
  • Space Elevator [POJ2392] [DP][优化]

    题目大意

    n件物品,第i件hi高,有ci件,最高的一件不能超过ai的高度。问最高能堆多高

    输入:

    第一行,一个n

    接下来每一行,为hi,ai,ci

    输出,最高堆多高

    样例输入:

    3
    7 40 3
    5 23 8
    2 52 6

    样例输出:

    48 (从下到上:3个2号,3个1号,6个3号)

    分析:

    我们很容易想到要先放限制高度小的,那我们就先按限制高度从小到大排序。

    然后我们可以发现,这个和多重背包很像,“物重”“价值”都为hi,数量为ci

    设dp[i][j]为用前i件,花费高度j的盒子,最高能堆多高(显然dp[][j]=j/0)。

    那么状态转移方程为dp[i][j]=max{dp[i-1][j-k*hi]+hi*k}其中限制条件是(dp[i-1][j-k*hi]!=0或j==k*hi )

    但我们发现这个复杂度是不优秀的,我们需要降复杂度。

    以下是优化方法{

    我们知道,0/1背包和完全背包只需要改变循环方向就行了。

    而完全背包从小到大循环就是保证了在更新了标号小的后,计算标号大的时候利用小的就可以使用更新后的值,从而实现“物品无限”。

    而我们多重背包是有限的个数,如何在完全背包上动点手脚?

    我们在dp[j]相对记录一个usd[j]表示已经用了这个物品几次了。

    在保证条件dp[j-hi]!=0或j==hi 和dp[j-hi]+hi>dp[j]时

    还需满足usd[j-hi]+1<=ci,再把usd[j]更新成usd[j-hi]+1,这样就能保证该物品使用次数小于等于ci。

    最后输出结果小心坑,找到第一个dp[i]不等于0,输出;特判ans==0的情况

    代码:

     1 #include<set>
     2 #include<map>
     3 #include<queue>
     4 #include<stack>
     5 #include<cmath>
     6 #include<cstdio>
     7 #include<cstring>
     8 #include<iostream>
     9 #include<algorithm>
    10 #define RG register int
    11 #define rep(i,a,b)    for(RG i=a;i<=b;++i)
    12 #define per(i,a,b)    for(RG i=a;i>=b;--i)
    13 #define ll long long
    14 #define inf (1<<29)
    15 #define maxn 405
    16 #define maxm 40005
    17 using namespace std;
    18 int n;
    19 int dp[maxm],usd[maxm];
    20 struct Dat{
    21     int w,a,c;
    22     inline int operator < (const Dat &tt)const{
    23         return a<tt.a;
    24     }
    25 }p[maxn];
    26 inline int read()
    27 {
    28     int x=0,f=1;char c=getchar();
    29     while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    30     while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
    31     return x*f;
    32 }
    33 int main()
    34 {
    35     n=read();
    36     int mx=0;
    37     rep(i,1,n)    p[i].w=read(),p[i].a=read(),p[i].c=read();
    38     sort(p+1,p+1+n);
    39     rep(i,1,n)
    40     {
    41         memset(usd,0,sizeof(usd));
    42         rep(j,p[i].w,p[i].a)
    43             if((j==p[i].w||dp[j-p[i].w]) && dp[j-p[i].w]+p[i].w>dp[j] && usd[j-p[i].w]+1<=p[i].c)
    44                 dp[j]=dp[j-p[i].w]+p[i].w,
    45                 usd[j]=usd[j-p[i].w]+1;
    46     }
    47     per(i,p[n].a,1)    if(dp[i]){cout<<dp[i];return 0;}
    48     puts("0");
    49     return 0;
    50 }
    View Code
  • 相关阅读:
    petshop4.0 详解之三(PetShop数据访问层之消息处理)
    MemberShip的使用
    PetShop 详解之一 系统架构设计
    PetShop4,错误提示:没有为 SQL 缓存通知启用数据库"MyCard"
    PetShop4,错误提示:System.Web.Security.SqlMembershipProvider”要求一个与架构版本“1”兼容的数据
    【Linux从零开始】:1.文件与目录的管理和配置(1)
    【笔记】在.NET中使用强类型有以下优点:
    【好文收藏】:Linq to DataSet
    【好文收藏】泛型与非泛型的比较(百度文库)
    HDOJ1102 Constructing Roads[Prim()]
  • 原文地址:https://www.cnblogs.com/ibilllee/p/9217535.html
Copyright © 2011-2022 走看看