首页 > 技术文章 > 【动态规划】多重背包

asuml 2016-08-03 17:23 原文

贵有恒,何必三更起五更眠;最无益,莫过一日曝十日寒。

【动态规划】多重背包

时间限制: 1 Sec  内存限制: 64 MB
提交: 5  解决: 5
[提交][状态][讨论版]

题目描述

张琪曼:“魔法石矿里每种魔法石的数量看起来是足够多,但其实每种魔法石的数量是有限的。”

李旭琳:“所以我们需要改变装包策略啦。”

现有N(N≤10)种魔法石和一个容量为V(0<V<200)的背包。第i种魔法石最多有n[i]件可用,每个占用的空间是c[i],价值是w[i]。全部物品总数不超过50。求解将哪些魔法石装入背包可使这些物品的容量总和不超过背包容量,且价值总和最大。

输入

第一行为两个数字,即V和N。以下N行为每种物品的空间,价值和数量。

输出

最大价值总和。

样例输入

8 2
2 100 4
4 100 2

样例输出

400


#include <iostream>
#include <cstring>
#define INF 0x3f3f3f3f
using namespace std;
int f[222],v[11],w[11],num[11];
int n,m;

//m背包的总容量、v物品的体积、w物品的价值
void OneZeroPack(int m,int v,int w)  //0-1背包
{
    for(int i=m;i>=v;i--)
        f[i]=max(f[i],f[i-v]+w);
}

//m背包的总容量、v物品的体积、w物品的价值
void CompletePack(int m,int v,int w)  //完全背包
{
    for(int i=v;i<=m;i++)
        f[i]=max(f[i],f[i-v]+w);
}

//m背包的总容量、v物品的体积、w物品的价值、num物品的数量
void MultiplePack(int m,int v,int w,int num)//多重背包
{
    if(v*num>=m)
    {
        CompletePack(m,v,w);
        return ;
    }
    int k=1;
    for(k=1;k<=num;k<<=1)
    {
        OneZeroPack(m,k*v,k*w);
        num=num-k;
    }
    if(num)
        OneZeroPack(m,num*v,num*w);
}

int main()
{
    while(cin>>m>>n)
    {
        for(int i=0;i<n;i++)
            cin>>v[i]>>w[i]>>num[i];
        memset(f,0,sizeof(f));
        for(int i=0;i<n;i++)
        {
            MultiplePack(m,v[i],w[i],num[i]);
        }
        cout<<f[m]<<endl;
    }
    return 0;
}

 

 

推荐阅读