多重背包

来源:互联网 发布:移动网络维护人员体检 编辑:程序博客网 时间:2024/05/16 15:29

HDU 2191

我们可以将多重背包分解为0-1背包和完全背包,当物品的(价格*数量)超过总金额时就可以看做是完全背包问题反之就可以看做是0-1背包问题。在转化成0-1背包时有个地方需要注意,我们可以把第i中物品的数量c[i]分成若干数量的集合比如物品i的数量有7种,就可以化为{1,2,4}可以用这集合里面三个元素组合成1~7中任意一种数量,分解的方法为:1,2,4,…….,c[i]-2^k+1

#include <iostream>  #include <cstring>#include <cstdio>#include <algorithm>#include <string>using namespace std;const int maxn = 110;int n, m;int dp[maxn], p[maxn], h[maxn], c[maxn];void CompleteBack(int v, int w){    for (int i=v; i <= n; i++)    {        dp[i] = max(dp[i], dp[i - v] + w);    }}void OnePack(int v, int w){    for (int i = n; i >= v; i--)    {        dp[i] = max(dp[i], dp[i - v] + w);    }}int main(){    int C, k = 1, count = 0;    cin >> C;    while (C--)    {        cin >> n >> m;//经费 种类        memset(dp, 0, sizeof(dp));        for (int i = 1; i <= m; i++)        {            cin >> p[i] >> h[i] >> c[i];//价格 重量 数量            if (p[i] * c[i] >= n)                CompleteBack(p[i], h[i]);//完全背包            else            {                   for (int j = 1; j <=c[i]; (j<< 1))                {                    OnePack(j*p[i], j*h[i]);//0-1背包                    c[i] = c[i] - j;                }                OnePack(p[i] * c[i], h[i] * c[i]);                          }        }        cout << dp[n] << endl;    }   }
原创粉丝点击