poj 2392 space elevator

题意:有一群牛要上太空,他们计划建一个太空梯(用一些石头垒),他们有k种不同类型的石头,每一种石头的高度为h,数量为c,由于会受到太空辐射,每一种石头不能超过这种石头的最大建造高度a;

我们来简化一下这个问题,现在有n个物品,每个物品的质量为w[i],每个物品有都有c[i]件,问在V为容量的包里的最大价值量是什么,这就是一个多重背包问题。


多重背包(MultiplePack): 有N种物品和一个容量为V的背包。第i种物品最多有n[i]件可用,每件费用是c[i],价值是w[i]。求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量,且价值总和最大。


这题目和完全背包问题很类似。基本的方程只需将完全背包问题的方程略微一改即可,因为对于第i种物品有n[i]+1种策略:取0件,取1件……取n[i]件。令f[i][v]表示前i种物品恰放入一个容量为v的背包的最大权值,则有状态转移方程:


f[i][v]=max{f[i-1][v-k*c[i]]+k*w[i]|0<=k<=n[i]


但是这道题做出了改变,把背包的容量变成了对高度的限制,在思想上是一样的,我们可以利用多重背包的思想,再加以改动。

这道题目是要求每一种石头不能超过这种石头的最大建造高度a;

那么我们用dp[i][j]表示用前i个物品能不能达到j这个高度

user[i][j]表示第i个物品在高度为j的时候用掉的数量。

我们可以用滚动数组进行优化,dp[i][j]->dp[j] user[i][j]->user[j];


那么dp方程就是dp[j]=dp[j]||dp[j-h[i]] 在转移的同时更新user

答案就是max f[j]==true


如下代码:

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define N 41000
    using namespace std;
    struct Node
    {
        int a,h,c;    
    }e[N];
    bool cmp(const Node& A,const Node &b)
    {
        return A.a<b.a;
    }
    int n,Max=0,user[N];
    bool dp[N];
    int main()
    {
         scanf("%d",&n);
         memset(dp,false,sizeof(dp));
         for(int i=1;i<=n;i++)
         {
             scanf("%d%d%d",&e[i].h,&e[i].a,&e[i].c);       
         }   
         sort(e+1,e+n+1,cmp);
         dp[0]=true;
         for(int i=1;i<=n;i++)
         {
               memset(user,0,sizeof(user));
               for(int j=e[i].h;j<=e[i].a;j++)
               {
                    if(!dp[j]&&dp[j-e[i].h]&&user[j-e[i].h]+1<=e[i].c)
                    {
                        dp[j]=true;
                        user[j]=user[j-e[i].h]+1;
                        if(Max<j)
                            Max=j;    
                    }
               }     
         }
         cout<<Max;
         //while(1);
         return 0;
    }

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值