AC_5. 多重背包问题 II

代码:

//多重背包优化(二进制)
/*
1.怎么把多重背包问题转换为01背包问题
v,w拆开重复s份放到数组里面去,每个物品只能用一次

=> 二进制拆法
7  7以内选多少个数可以使得7中所有的数都可以组合出来  0-7
1 1 1 1 1 1 1

1 2 4
0
1
2
3 =  1 + 2
4 = 4
5 = 1 + 4
6 = 2 + 4
7 = 1 + 2 + 4

给定一个数s,用多少个数可以表示小于等于s的所有数  答案 log2(s)上取整
s = 10
1 2 4 3
1 2 7 :0-7
3: 0-10

s - 1 - 2 - 4 - 8  分成了log(s)份
1000*log(2000)*2000 = 1000*11*2000 = 2 * 10^7
*/
#include<iostream>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
const int NUM = 2010;
int N, V;
int dp[NUM];
//定义结构体 v体积,w表示价格
struct Good{
    int v, w;
};
int main()
{
    vector<Good>goods;//不知道总共的物品有多少个
    cin >> N >> V;
    for (int i = 0; i < N; i++)
    {
        int v, w, n;
        cin >> v >> w >> n;
        for (int k = 1; k <= n; k *= 2)//拆成2的整次幂
        {
            n -= k;
            goods.push_back({ v*k, w*k });//放到物品组中去
        }
        if (n>0)
            goods.push_back({ v*n, w*n });//剩余的
    }
    // 01背包求最大价值
    for (auto good:goods)
        for (int j = V; j >= good.v; j--)
        {
            dp[j] = max(dp[j], dp[j - good.v] + good.w);
        }
    cout << dp[V] << endl;
    return 0;
}

 

posted @ 2019-07-21 23:08  A-inspire  Views(205)  Comments(0Edit  收藏  举报