超大背包问题(01背包)
超大背包问题:有n个重量和价值分别为w[i]和v[i]的物品,从这些物品中挑选总重量不超过W的物品,求所有挑选方案中价值总和的最大值。其中,1 ≤ n ≤ 40, 1 ≤ w[i], v[i] ≤ 10^15, 1 ≤ W ≤ 10^15.
这个问题给人的第一感觉就是普通的01背包。不过,看完数据范围会发现,这次价值和重量都可以是非常大的数值,相比之下n比较小。使用DP求解背包为题的复杂度是O(nW),因此不能用来解决这个问题。此时我们应该利用n比较小的特点来寻找其他方法。
挑选物品的方案总共有2^n种,所以不能直接枚举,但是如果将物品分成两半再枚举的话,由于每部分最多只有20个,这是可行的。我们把前半部分中的挑选方法对应的重量和价值总和记为w1、v1,这样在后半部分寻找总重w2 ≤ W - w1时使v2最大的选取方法即可。
因此,我们要思考从枚举得到的(w2,v2)集合中高效寻找max{v2|w2 ≤ W'}的方法。首先,显然我们可以排除所有w2[i] ≤ w2[j] 并且 v2[i] >= v2[j]的j。这一点可以按照w2、v2的字典序排序后做到。此后剩余的元素都满足w2[i] < w2[j] <=> v2[i] < v2[j],要计算max{v2|w2 <= W'}的话,只要寻找满足w2[i] <= W'的最大的i就可以了。这可以用二分搜索完成,剩余的元素个数为M的话,一次搜索需要O(logM)的时间。因为M≤2^(n/2),所以这个算法总的时间复杂度是O(n * 2^(n/2)),可以在实现内解决问题。
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 50;
const long long INF = 0x3fffffff;
typedef long long LL;
int n;
LL w[N], v[N];
LL W;
pair <LL, LL> pi[1 << (N / 2)];void solve() {int n2 = n / 2;for(int i = 0; i < (1 << n2); i++) {LL sw = 0, sv = 0;for(int j = 0; j < n2; j++) {if((i >> j) & 1) {sw += w[j];sv += v[j];}}pi[i] = make_pair(sw, sv);}sort(pi, pi + (1 << n2));int m = 1;for(int i = 1; i < (1 << n2); i++) {if(pi[m-1].second < pi[i].second) {pi[m++] = pi[i];}}LL res = 0;for(int i = 0; i < (1 << (n - n2)); i++) {LL sw = 0, sv = 0;for(int j = 0; j < n - n2; j++) {if((i >> j) & 1) {sw += w[n2 + j];sv += v[n2 + j];}}if(sw <= W) {LL tv = (lower_bound(pi, pi + m, make_pair(W - sw, INF)) - 1)->second;res = max(res, sv + tv);}}printf("%lld\n", res);
}int main() {while(~scanf("%d%lld", &n, &W)) {for(int i = 0; i < n; i++) {scanf("%lld%lld", &w[i], &v[i]);}solve();}return 0;
}
超大背包问题(01背包)相关推荐
- 背包问题——01背包
背包问题--01背包 01背包作为动态规划(dynamic programing)中最基础的问题,需要我们彻底理解其中的原理,为以后解决更难的动态规划问题打下良好的基础. 这里拟定一个01背包问题: ...
- 动态规划之背包问题——01背包
算法相关数据结构总结: 序号 数据结构 文章 1 动态规划 动态规划之背包问题--01背包 动态规划之背包问题--完全背包 动态规划之打家劫舍系列问题 动态规划之股票买卖系列问题 动态规划之子序列问题 ...
- C++ 背包问题——01背包
由于编辑器原因,01背包文章搬家了,想看到更好的01背包问题题解,请点击链接: C++背包问题--01背包_小天狼星_布莱克的博客-CSDN博客
- 经典背包问题 01背包+完全背包+多重背包
01 背包 有n 种不同的物品,每个物品有两个属性,size 体积,value 价值,现在给一个容量为 w 的背包,问最多可带走多少价值的物品. int f[w+1]; //f[x] 表示背包容量为x ...
- 背包问题——01背包/完全背包/多重背包
背包问题是典型的动态规划问题,本文将对典型的背包问题进行总结. 0-1背包问题 有 N 件物品和一个容量是 V 的背包.每件物品只能使用一次. 第 i 件物品的体积是 vi,价值是 wi. 求解将哪些 ...
- 动态规划之背包问题---01背包---完全背包---多重背包
本篇博客是基于Carl大佬的刷题笔记 (代码随想录) 进行总结的 另外加入了我自己的一些整理,特此记录,以防遗忘 几种在面试中常见的背包,其关系如下: 通过这个图,可以很清晰分清这几种常见背包之间的关 ...
- C++背包问题——01背包
01背包问题 1.题目 2.基本思路 3.优化空间复杂度 4.初始化的细节问题 5.小结 6.代码 1.题目 有N件物品和一个容量为 V V V的背包.放入第i件物品耗费的空间是 C i Ci Ci, ...
- 动态规划之背包问题 01背包
什么是01背包? 有n件物品和一个最多能背重量为w 的背包.第i件物品的重量是weight[i],得到的价值是value[i] .每件物品只能用一次,求解将哪些物品装入背包里物品价值总和最大. 首先, ...
- 动态规划背包问题——01背包
2022.7.20 题意概要:有n个物品和一个容量为p的背包,每个物品有重量w和价值v两种属性,要求选若干物品放入背包使背包中物品的总价值最大且背包中物品的总重量不超过背包的容量. 在 ...
- 动态规划——背包问题01背包
有n件物品和一个最多能背重量为w 的背包.第i件物品的重量是weight[i],得到的价值是value[i] .每件物品只能用一次,求解将哪些物品装入背包里物品价值总和最大. 动态规划五部曲: 确定d ...
最新文章
- 立刻停止使用AUFS,开启Overlay!
- EEG伪影详解和过滤工具的汇总(二)
- nyoj983 首尾相连数组的最大子数组和
- linux 函数 文件校验,Linux中的文件效验命令
- sqlserver中能用when_【SQL】SQL中Case When的用法
- TableView Within Alert
- ODBC数据源的配置方法
- 集成计划排程计划以及管控体系的几个特征
- 在EF4.1的DBContext中实现事务处理(BeginTransaction)和直接执行SQL语句的示例
- java 字符串换行问题
- C++中list的各种使用
- javaeye API
- linux格式化分区进程,Linux 硬盘格式化、分区、挂载、卸载、删除分区,Linux重新调整分区...
- 苹果ocr文字识别工具:Text Scanner
- [休闲]GDC China 2007上海中国游戏开发者大会
- Google guava之Table简介说明
- 幸福的烦恼:显卡算力太高而pytorch版本太低不支持
- 计算机毕业设计 SSM+Vue农家乐管理系统 农家院住宿管理系统 民宿旅游预约管理系统 Java Vue MySQL数据库 远程调试 代码讲解
- 罗永浩疑回应再被强制执行
- datagrid设置单元格边框_如何设置datagridview某一个单元格的边框样式