超大背包问题(折半枚举, 双向搜索)
有重量和价值分别为wi, vi (1 <= wi, vi <= 1e15)的n (1 <= n <= 40)个物品,从中挑选总重不超过W(1 <= W <= 1e15)的物品,求价值总和最大值。
这是典型的01背包问题,不过dp求解复杂度为O(nW),这里W太大了,因此无法求解。挑选物品方法共有2^n种,也无法直接枚举。但是拆成两半再枚举的话还是可行的,每部分最多只有20个。假设第一部分某个选取方法对应的重量和价值为w1, v1,那么只要在第二部分中寻找w2+w1<=W且v2最大的方法就行了。寻找时可以用二分查找,总时间复杂度为O(2^(n/2)n),可以接受。
#include <iostream>
#include <sstream>
#include <fstream>
#include <string>
#include <map>
#include <vector>
#include <list>
#include <set>
#include <stack>
#include <queue>
#include <deque>
#include <algorithm>
#include <functional>
#include <iomanip>
#include <limits>
#include <new>
#include <utility>
#include <iterator>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cctype>
#include <cmath>
#include <ctime>
using namespace std;
typedef long long LL;
const int maxn = 50;
const LL INF = 0x3f3f3f3f;int n;
LL w[maxn], v[maxn];
LL W;
pair<LL, LL> ps[1<<(maxn/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];}ps[i] = make_pair(sw, sv);}//去除多余的元素sort(ps, ps+(1<<n2));int m = 1;for (int i = 1; i < (1<<n2); ++i)if (ps[m-1].second < ps[i].second)ps[m++] = ps[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(ps, ps + 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;
}/*
Sample Input
4 5
2 3
1 2
3 4
2 2
Sample Output
7
*/
超大背包问题(折半枚举, 双向搜索)相关推荐
- 超大背包问题(二进制枚举 + 二分)
超大背包问题 第一次看到这一题好像是在某一场比赛,就是给你一个炸空间和时间的背包,让你选最大的价值,看似是01背包然鹅今天在挑战程序设计这本书上看到了这题,看到了作者的做法,感觉豁然开朗,直接暴搜也会 ...
- Subset POJ - 3977(折半枚举+二分+二进制枚举)
题意: 给你一个集合N(N<=35),问集合的子集,除了空集,使得自己中所有元素和的绝对值最小,若存在多个值,那么选择子集中元素最少的那个. 题目: Given a list of N inte ...
- 2017西安交大ACM小学期 刁钻的顾客[3进制+折半枚举]
刁钻的顾客 发布时间: 2017年7月3日 10:23 时间限制: 3000ms 内存限制: 128M 描述 XJTU校园内新开一家商店,可是来了一位刁钻的顾客要购买商品A和商品B.关于商品的 ...
- poj_3977 折半枚举
题目大意 给定N(N<=35)个数字,每个数字都<= 2^15. 其中一个或多个数字加和可以得到s,求出s的绝对值的最小值,并给出当s取绝对值最小值时,需要加和的数字的个数. 题目分析 需 ...
- CodeForces888E Maximum Subsequence(折半枚举+two-pointers)
题意 给定一个包含\(n\)个数的序列\(a\),在其中任选若干个数,使得他们的和对\(m\)取模后最大.(\(n\leq 35\)) 题解 显然,\(2^n\)的暴枚是不现实的...,于是我们想到了 ...
- POJ 3373 模运算 + 折半枚举
题意 传送门 POJ 3373 题解 置换 nnn 部分数位上的数字得到 mmm,其能被 kkk 整除,且置换数位最少,有多个 mmm 满足上述条件则求最小值. 考虑到 k≤104k\leq 10^4 ...
- zstu新生赛 Problem A: Baby Coins(折半枚举+二分)
Problem A: Baby Coins Time Limit: 1 Sec Memory Limit: 128 MB Submit: 274 Solved: 29 Description Baby ...
- P4799-世界冰球锦标赛(折半枚举模板)
题目 1<=n<=40,1<=m<=1e18; 输入样例#1: 5 1000 100 1500 500 500 1000 输出样例#1: 8 01背包,m范围小的话可以使用.这 ...
- 【HDU 5936 --- Difference】折半枚举+二分
[HDU 5936 --- Difference]折半枚举+二分 Description Little Ruins is playing a number game, first he chooses ...
- 折半枚举(双向搜索)
1. 从 4 个数列中选择的话总共有 n4 种情况,所以全都判断一遍不可行.不过将它们对半分成 AB 和 CD 再考虑,就可以快速解决了.从两个数列中选择的话只有 n2 种组合,所以可以进行枚举.先从 ...
最新文章
- 网络负载均衡相关技术-DNS
- MySQL/phpmyadmin问题解决手记:#2002 – 服务器没有响应 (或者本地 MySQL 服务器的套接字没有正确配置)
- S4HANA里至关重要的建模方式CDS view架构介绍
- java 不规则 拼图_Java中不一致的操作会扩大规则
- [css] 你了解css3的currentColor吗?举例说明它的作用是什么?
- MySQL DQL语言的笔记
- Spring 框架基础(02):Bean的生命周期,作用域,装配总结
- 20155307 2016-2017-2 《Java程序设计》第4周学习总结
- kafka 同步提交 异步_Kafka 位移提交那些事儿
- 苹果电脑获取Android Studio的发布版SHA1和开发版SHA1
- 关于JAVA小程序完整打包过程
- java 快逸报表_数据填报 | 快逸报表工具-Java报表软件
- 倪光南、求伯君“出山”:爱解 Bug、无惧“35岁魔咒”、编码之路痛并快乐!...
- 磁力计椭球拟合使用篇 IMU 加速度、电子罗盘校准
- 实验室服务器系统崩溃,选课系统崩溃解救报告
- 值得感谢的10位顶级游戏制作人
- 带你走出计算机安全防范的六个误区
- 大数据是如何定义,多大的数据是大数据?
- 开机出现checking file system on C或者D E F盘符的解决方法
- 2016-5-5 早
热门文章
- ubuntu开机时出现“waiting for network configuration” 问题的解决
- PHP判断远程url是否有效的几种方法
- C++类引用中的构造函数与析构函数的执行顺序练习
- 两款工控控件对比评测:Iocomp和ProEssentials
- HTML5SVG 游戏开发 【起航】
- Tomcat StringManager阅读学习 -我们到底能走多远系列(10)
- MOSS Search学习记录(八):高级搜索定制(中)
- [lua]紫猫lua教程-命令宝典-L1-01-11. lua的个人补充
- IIS7下访问ashx页面,显示404
- 《我们不一样团队》项目需求分析改进