【题目来源】
https://www.luogu.com.cn/problem/P1776
【题目描述】
终于,破解了千年的难题。小 F 找到了王室的宝库,里面堆满了无数价值连城的宝物。
这下小 F 可发财了,嘎嘎。但是这里的宝物实在是太多了,小 F 的采集车似乎装不下那么多宝物。看来小 F 只能含泪舍弃其中的一部分宝物了。
小 F 对宝库里的宝物进行了整理,他发现每样宝物都有一件或者多件。他粗略估算了下每样宝物的价值,之后开始了宝物筛选工作:小 F 有一个最大载重为 W 的采集车,宝库里总共有 n 种宝物,每种宝物的价值为 vi,重量为 wi,每种宝物有 mi 件。小 F 希望在采集车不超载的前提下,选择一些宝物装进采集车,使得它们的价值和最大。
【输入格式】
第一行为一个整数 n 和 W,分别表示宝物种数和采集车的最大载重。
接下来 n 行每行三个整数 vi,wi,mi。
【输出格式】
输出仅一个整数,表示在采集车不超载的情况下收集的宝物的最大价值。
【算法分析】
多重背包问题通常可转化成01背包问题求解。但若将每种物品的数量拆分成多个1的话,时间复杂度会很高,从而导致TLE。所以,需要利用二进制优化思想。即:
一个正整数n,可以被分解成1,2,4,…,2^(k-1),n-2^k+1的形式。其中,k是满足n-2^k+1>0的最大整数。
例如,假设给定价值为2,数量为10的物品,依据二进制优化思想可将10分解为1+2+4+3,则原来价值为2,数量为10的物品可等效转化为价值分别为1*2,2*2,4*2,3*2,即价值分别为2,4,8,6,数量均为1的物品。
【算法代码】
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53#include <bits/stdc++.h> using namespace std; int n,V; const int maxn=100005; int vol[maxn],val[maxn]; int c[maxn]; int main() { cin>>n>>V; int cnt=0; for(int i=1; i<=n; i++) { int wi,vi,nge; cin>>vi>>wi>>nge; int k=1; while(k<=nge) { cnt++; vol[cnt]=wi*k; val[cnt]=vi*k; nge-=k; k*=2; } if(nge>0) { cnt++; vol[cnt]=wi*nge; val[cnt]=vi*nge; } } n=cnt; for(int i=1; i<=n; i++) { for(int j=V; j>=vol[i]; j--) c[j]=max(c[j],c[j-vol[i]]+val[i]); } cout<<c[V]<<endl; return 0; } /* in: 4 20 3 9 3 5 9 1 9 4 2 8 1 3 out: 47 */
【参考文献】
https://blog.csdn.net/hnjzsyjyj/article/details/109363826
https://www.luogu.com.cn/problem/P1776
最后
以上就是务实毛衣最近收集整理的关于洛谷 P1776:宝物筛选 ← 多重背包问题 二进制优化的全部内容,更多相关洛谷内容请搜索靠谱客的其他文章。
发表评论 取消回复