(容量超大)or(容量及价值)超大背包问题 ( 折半枚举 || 改变 dp 意义 )
题意 :
以下两个问题的物品都只能取有且只有一次
① 给你 N 个物品,所有物品的价值总和不会超过 5000, 单个物品的价格就可达 10^10 ,背包容量为 B
② 给你 N (N ≤ 40 ) 个物品,物品的单个价值和重量都达到 10^15 问你在背包容量为 W
给出 ① 和 ② 问题条件下背包所能装出来的最大价值
分析 :
① 因为单个物品的价值实在太大,如果仍然按照普通 0/1 背包的 dp 定义方法数组是开不下的
但是发现价值的总和并不大,所以从价值这里下手,定义 dp[i][j] = 从 1 ~ i 个物品背包价值为 j 时的最小重量
dp 的状态转移方程效仿普通的 0/1 背包即可,但是是取最小 dp[i][j] = min(dp[i][j], dp[i-1][j-v[i]] + w[i])
同样可以使用 0/1 背包的空间优化将 dp 数组转化为一维的来减少空间复杂度
以下是 FZU 2214 的 AC 代码
#include<stdio.h> #include<string.h> #include<algorithm> #define LL long long using namespace std; ; const LL INF = 0x3f3f3f3f; LL dp[maxn], w[], B; ]; int N, C; int main(void) { int nCase; scanf("%d", &nCase); while(nCase--){ scanf("%d %lld", &N, &B); C = ; ; i<=N; i++) scanf("%lld %lld", &w[i], &v[i]), C += v[i]; /// C 累加的是所有物品的价值总和 ; j<=C; j++) dp[j] = INF;/// 初始化 dp 数组应当赋予一个较大的数 dp[] = ; ; i<=N; i++) for(int j=C; j>=v[i]; j--) dp[j] = min(dp[j], dp[j-v[i]]+w[i]); ; j--){ if(dp[j] <= B){///从大到小遍历价值,第一个满足条件的 dp 数组值的下标便是答案 printf("%d\n", j); break; } } } ; }
② 因为价值和重量都太过于大,数组是完全开不下了,不能记录状态,所以考虑其他方法。
如果是去暴力,那么就是暴力枚举物品的组合,然后找到一个组合使得价值最大,复杂度为 O( 2^n )
这里 max( n ) == 40 ,所以时间复杂度还是大到无法接受,考虑是否能将问题规模降下来。
考虑折半枚举法,假设现 n == 40,折半思想是先把前 2^20 个物品的组合先枚举预处理出来 2^20 个 w、v
然后如果我们能对于这枚举出来的前 2^20 个和后面 2^20 个物品的某个组合结合然后找出最优的结果
最后从这 2^20 个最优结果中再取最优就是答案,问题就是如何对于预处理出来的前 2^20 个组合与后面结合产生最优
假设现在背包容量为 C ,在前 2^20 个物品组合中取出一个,价值为 vi 重量为 wi
那么如果我们能从后 2^20 个中找出一个组合使得其在满足重量 w' ≤ C - wi 的情况下价值最大
只要对于后 2^20 个的所有组合处理出其重量和价值,然后根据重量排序且根据价值去重
这样就能用二分查找来加快查找速度!
#include<bits/stdc++.h> #define LL long long using namespace std; ; const LL INF = 0x3f3f3f3f; pair<LL, LL> Pi[<<(maxn/)]; LL W[maxn], V[maxn], C; int N; int main(void) { //freopen("in.txt", "r", stdin); while(~scanf("%d %lld", &N, &C)){ ; i<N; i++) scanf("%lld %lld", &W[i], &V[i]); ; ; i<(<<n); i++){/// 利用二进制法枚举子集,集合个数应当为 2^n LL SumW, SumV; SumW = SumV = ; ; j<n; j++){ ){ SumW += W[j]; SumV += V[j]; } } Pi[i] = make_pair(SumW, SumV);/// 将每个组合的 重量&&价值 用 pair 存起来 } sort(Pi, Pi+(<<n));/// 按照第一键值(重量)排序 ; ; i<(<<n); i++) ].second < Pi[i].second)/// 这样的去重能找出在价值一样的情况下,保存最小的 w Pi[num++] = Pi[i]; ; i<num; i++){ printf("%d %lld %lld", i, Pi[i].first, Pi[i].second); puts(""); } LL res = ; ; i<(<<(N-n)); i++){/// 枚举后半段的组合 LL SumW, SumV; SumW = SumV = ; ; j<(N-n); j++){ ){ SumW += W[n+j]; SumV += V[n+j]; } } if(SumW <= C){ ; pair<LL, LL> Temp = Pi[idx]; res = max(res, SumV + Temp.second); } } printf("%lld\n", res); } ; }
(容量超大)or(容量及价值)超大背包问题 ( 折半枚举 || 改变 dp 意义 )的更多相关文章
- 中南林业大学校赛 I 背包问题 ( 折半枚举 || 01背包递归写法 )
题目链接 题意 : 中文题 分析 : 价值和重量都太过于大,所以采用折半枚举的方法,详细可以看挑战的超大背包问题 由于 n <= 30 那么可以不必直接记录状态来优化,面对每个用例 直接采用递 ...
- NYOJ 1091 超大01背包(折半枚举)
这道题乍一看是普通的01背包,最最基础的,但是仔细一看数据,发现普通的根本没法做,仔细观察数组发现n比较小,利用这个特点将它划分为前半部分和后半部分这样就好了,当时在网上找题解,找不到,后来在挑战程序 ...
- CSU OJ PID=1514: Packs 超大背包问题,折半枚举+二分查找。
1514: Packs Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 61 Solved: 4[Submit][Status][Web Board] ...
- FZU 2214 ——Knapsack problem——————【01背包的超大背包】
2214 Knapsack problem Accept: 6 Submit: 9Time Limit: 3000 mSec Memory Limit : 32768 KB Proble ...
- 关于ArrayList 容量问题
ArrayList 是实现List 接口的动态数组,即它的容量大小是可变的.允许包括null 在内的所欲元素. 每个ArrayList 实例都有一个容量,该容量是指用来存储列表元素的数组的大小.默认初 ...
- Java中的ArrayList的初始容量和容量分配
List接口的大小可变数组的实现.实现了所有可选列表操作,并允许包括 null 在内的所有元素.ArrayList继承于List接口,除继承过来的方法外,还提供一些方法来操作内部用来存储列表的数组的大 ...
- SharePoint咨询师之路:设计之前的那些事一:容量
提示:本系列只是一个学习笔记系列,大部分内容都可以从微软官方网站找到,本人只是按照自己的学习路径来学习和呈现这些知识. 咨询师更多的时候是解决方案提供者,那么他们如何能够提供有效的SharePoint ...
- Android读取RAM,ROM,SD卡容量
1)简介 一般人们在买手机的时候,在手机配置上都会出现"内存容量:512MB ROM+512MB RAM "等等类似这样的说明,可能很多人都知道RAM的意思就是运存的意思,但是对于 ...
- 额定能量不得超过160Wh, 等同是多少mAh电池容量?
额定能量不得超过160Wh, 等同是多少mAh电池容量?行动电源容量标示, 正确应该是用Whr(Wh)瓦特小时来标示, 不过坊间标榜行动电源的容量通常是用xx000mAhWHr瓦特小时, 即是行动电源 ...
随机推荐
- VBA计算器的全部实现
我们将加入 除零逻辑 和 对话框提示. 后面 就很简单了~~~ 提供效果图跟 代码 代码示例 Sub 矩形1_Click() ' ' 矩形1_Click Macro ' 代码编辑 Dim number ...
- Lesson 5 The facts
go to extremes走极端 provide... with...向..提供.. go to press付印 suspicious,adj. 可疑的:怀疑的:多疑的 fired---同义词--- ...
- iptables添加开放端口
查看状态 iptables -L -n 编辑/etc/sysconfig/iptables -A INPUT -p tcp -m tcp --dport 4000 -j ACCEPT 重启 servi ...
- js while循环
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8" ...
- 如何上传大文件到github上
真的是被百度坑怕了,只适合我自己的 如果你之前安装git成功的话,右键会出现两个新选项,分别为Git Gui Here,Git Bash Here,这里我们选择Git Bash Here,进入如下界面 ...
- 在laravel框架中使用mq
本文写于2018-11-28 1.部署laravel项目 https://github.com/laravel/laravel 通过git克隆项目,或者下载zip包然后解压等方式都可以把larave ...
- Ubuntu 16.04简单配置备忘录
1.几个安装包的地址 1.Linux QQ:https://im.qq.com/linuxqq/index.html 2.网易云音乐:http://s1.music.126.net/download/ ...
- Python模块logging
基本用法: import logging import sys # 获取logger实例,如果参数为空则返回root logger logger = logging.getLogger("A ...
- SVN的各种符号含义,svn的星号,感叹号,问号等含义
黄色感叹号(有冲突):--这是有冲突了,冲突就是说你对某个文件进行了修改,别人也对这个文件进行了修改,别人抢在你提交之前先提交了,这时你再提交就会被提示发生冲突,而不允许你提交,防止你的提交覆盖了别人 ...
- 搜索专题: HDU1501Zipper
Zipper Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Sub ...