超大多重背包问题
2015-12-29 16:30
393 查看
TopCoder SRM 674 div 1 ClassicProblem
Problem Statement | ||||||||||||
This task is about a classic problem in computer science: the knapsack problem. There are n types of items. The types are numbered 0 through n-1, inclusive. For each valid i, you havecnt[i] items of type i, and each of these items has weightw[i] and value v[i]. You are given the vector <int>scnt, w, and v. You are also given an intlimit. Find a subset of the available items such that: the total weight of the selected items is smaller than or equal to limit the total value of the selected items is as large as possible Return the total value of the selected items. | ||||||||||||
Definition | ||||||||||||
| ||||||||||||
Limits | ||||||||||||
| ||||||||||||
Constraints | ||||||||||||
- | cnt will contain between 1 and 80 elements, inclusive. | |||||||||||
- | cnt, w and v will contain the same number of elements. | |||||||||||
- | Each element in cnt will be between 1 and 1,000,000,000, inclusive. | |||||||||||
- | Each element in w will be between 1 and 80, inclusive. | |||||||||||
- | Each element in v will be between 1 and 1,000,000,000, inclusive. | |||||||||||
- | limit will be between 1 and 1,000,000,000, inclusive. | |||||||||||
Examples | ||||||||||||
0) | ||||||||||||
| ||||||||||||
1) | ||||||||||||
| ||||||||||||
2) | ||||||||||||
| ||||||||||||
3) | ||||||||||||
| ||||||||||||
4) | ||||||||||||
| ||||||||||||
5) | ||||||||||||
|
借鉴了别人的代码,将第i种物品拆分为若干件,每件物品的value:2^(k) * value[i]、weight:2^(k) * weight[i]。且 2^(k1) + 2^(k2) + ... + 2^(ki) == count[i]。保证这些系数可以组合成小于等于count[i]的任意值。
将limit也进行二进制拆分,维护一个状态dp[dx][maxs] 当前所处的二进制位为dx,背包容量为maxs时的最大值。
maxs的最大值取 N*2*2*MAX_WEIGHT。因为经过对count的拆解,每个dx下至多有N*2个值。且dx位上的0~maxs受dx-1位上0~maxs/2影响。
状态转移过程为:
从0到30枚举dx
找出limit在dx位的值d,求出dp[cur][i] = dp[pre][min(maxs-1, 2*i+d)];。因为当前维护的是剩余容量,所以当d为1时,剩余容量至少加一。
接下来就是常规的0/1 dp
#include <bits/stdc++.h> using namespace std; #define rep(i,a,b) for(int i=(a),__tzg_##i=(b);i<__tzg_##i;++i) #define urp(i,a,b) for(int i=(a),__tzg_##i=(b);i>=__tzg_##i;--i) #define rp(i,b) rep(i,0,b) #define repd(i,a,b) rep(i,a,(b)+1) #define mst(a,b) memset(a,b,sizeof(a)) #define vrp(it,v) for(auto it(v.begin());(it)!=(v.end());++it) #define vtr(v) (v).begin(),(v).end() #define mp(a,b) make_pair(a,b) #define fi first #define se second #define pb(a) push_back(a) #define _0(x) (!(x)) #define _1(x) (x) #define bit(x,y) (((x)>>(y))&1) typedef vector<int> VI; typedef pair<int,int> PII; typedef vector<PII> VPII; typedef long long ll; struct ClassicProblem { const static int M = 31, X = 81*81*2*2; VPII s[M]; ll dp[2][X]; VI divide(int x) { VI r; rp(i,M) if ((1<<i) <= x) r.pb(i), x -= 1<<i; else break; rp(i,M) if (bit(x,i)) r.pb(i); return r; } long long maximalValue(vector <int> cnt, vector <int> w, vector <int> v, int limit) { int n = cnt.size(); rp(i, n) { VI r = divide(cnt[i]); for (int e : r) s[e].pb(mp(w[i], v[i])); } int cur = 0, pre = 1-cur; mst(dp, 0); rp(pos, M) { cur = pre; pre = 1-pre; mst(dp[cur], 0); int d = pos?bit(limit, pos-1):0; rp(i, X) dp[cur][i] = dp[pre][min(X-1, 2*i+d)]; for (auto & e : s[pos]) { urp(i, X-1, e.fi) dp[cur][i] = max(dp[cur][i], dp[cur][i-e.fi]+(1ll<<pos)*(ll)e.se); } } return dp[cur][bit(limit, M-1)]; } }; int main() { ClassicProblem *f = new ClassicProblem; assert(f->maximalValue({17452733, 484, 607117, 44102867, 80917, 9955379, 154783, 79, 757486, 1800008, 31397, 66532052, 5, 8351, 30063, 538787, 66, 993, 28503205, 696813, 93438689, 9474478, 14716355, 93438689, 53851, 75482618, 6856, 93438689, 8033317, 31, 4, 2, 2957, 68, 536547, 240613, 19, 290847, 57242428, 1722, 19160318, 692, 73009, 5, 93438689, 1431, 8982}, {12, 22, 6, 16, 14, 20, 10, 7, 5, 2, 12, 11, 11, 10, 9, 5, 8, 3, 1, 18, 9, 7, 22, 21, 19, 12, 15, 20, 11, 17, 7, 14, 11, 15, 5, 4, 22, 6, 11, 21, 17, 20, 22, 18, 12, 6, 6}, {977866, 774579, 977866, 7, 54, 830, 3, 977866, 977866, 27341, 977866, 290, 9, 445629, 977866, 6, 525083, 1, 977866, 41533, 977866, 977866, 977866, 8, 4203, 977866, 62884, 2, 9, 977866, 5005, 2, 727, 9952, 977866, 977866, 275, 70, 61, 834, 651, 977866, 977866, 977866, 977866, 16488, 977866}, 38504) == 37651752464ll); return 0; }
相关文章推荐
- C#使用回溯法解决背包问题实例分析
- 关于背包问题的一些理解和应用
- C++动态规划之背包问题解决方法
- C#使用动态规划解决0-1背包问题实例分析
- 背包问题
- hdu2546
- HDU 2955
- 动态规划背包问题篇
- 简单0-1背包
- 背包九讲问题
- 背包问题knapsack的三种解法(Python 和 C)
- 动态规划问题 -- 背包问题 单价不等水果 装入固定容量背包 最大价值问题
- 背包问题knapsack的三种解法(Python 和 C)
- hihocoder #1091
- poj 3624
- poj 1976 01背包
- poj 1837分组背包
- poj 3046 分组背包
- poj 2063 完全背包
- poj1384 完全背包