POJ2392 Space Elevator (多重背包)

题目点我点我点我

题意:有一群奶牛向上太空,然后要用一块块塔搭上去,给出K种类型的塔,每种类型单块高度为h,在a高度一下都可以搭建,有c块。

思路:多重背包问题,在进行多重背包之前要进行一次排序,将最大高度小的放在前面,只有这样才能得到最优解,如果将大的放在前面,后面有的小的就不能取到,排序之后就可以进行完全背包了。
注意这题只有花费,没有价值,利用dp记录能搭建的所有高度的情况,能搭建到i高度就dp[i]=1,初始化dp[0]=1,因为有可能有答案为0的结果。好题!

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <algorithm>
using namespace std;
int dp[40010];
struct Block
{
    int h,c,a;    //h高度,c数量,a限制高度
}block[410];

void ZeroOnePack(int h,int a)
{
    for(int i=a;i>=h;i--)
        dp[i]=max(dp[i],dp[i-h]);
}

void CompletePack(int h,int a)
{
    for(int i=h;i<=a;i++)
        dp[i]=max(dp[i],dp[i-h]);
}

void MultipliesPack(int h,int a,int c)
{
    if(h*c>=a)CompletePack(h,a);
    else
    {
        for(int k=1;k<c;)
        {
            ZeroOnePack(k*h,a);
            c-=k;
            k<<=1;
        }
        ZeroOnePack(c*h,a);
    }
}

int compare(Block m,Block n)
{
    return m.a<n.a;
}

int main()
{
    int K;
    scanf("%d",&K);
    for(int i=1;i<=K;i++)
    {
        scanf("%d%d%d",&block[i].h,&block[i].a,&block[i].c);
    }
    sort(block+1,block+1+K,compare);
    memset(dp,0,sizeof(dp));
    dp[0]=1;             //也有可能是答案为零的情况
    for(int i=1;i<=K;i++)
    {
        MultipliesPack(block[i].h,block[i].a,block[i].c);
    }
    for(int i=block[K].a;i>=0;i--)
    {
        if(dp[i])
        {
            printf("%d\n",i);
            break;
        }
    }


    return 0;
}

你可能感兴趣的:(POJ2392 Space Elevator (多重背包))