题目大意

一个人收藏骨头,有 n 个骨头,每个骨头有体积和价值,问能够装在容量为 V 的背包中,能获得的第 k 大(去重后)价值是多少。

样例

样例输入 1

5 10 2
1 2 3 4 5
5 4 3 2 1

样例输出 1

12

样例输入 2

5 10 12
1 2 3 4 5
5 4 3 2 1

样例输出 2

2

分析

  • 跑暴力显然不优秀,每种物品可选可不选,最多 \(2^n\) 种不同的方案,也就对应这么多价值,显然如果都存下再排序输出结果,简单了事,但是显然时间和空间都承受不住。
  • 当然在跑背包的时候,我们每次的决策都是在前面的基础上求得当前阶段每个状态的最优解。如果单纯的想最后把数组中所有的值都拿来排序,也不可行。整个转移过程并不能保证比最优解小一点的就是次大值。
  • 我们可以针对每个容量 j,同时维护 k 个值,来保存放到容量 j 的时候前 k 大价值。在此基础上我们再考虑针对第 i 件物品的转移:
    • 定义 \(f[i][j][k]\) 表示前 i 件物品放到容量为 j 背包中,获得的第 k 大价值,由于第 i 捡物品状态转移的时候只跟前 i-1 的状态有关,因此还可以简化成二维,即 \(f[j][k]\)。
    • 放与不放第 i 件物品的最大值从何而来?很显然,就是普通的转移方程的两个值取较大者:\(max\{f[j][1], f[j-vi][1]+wi\}\),即放与不放分别有一个最大值,从二者当中选取一个作为最大。
    • 继续考虑第二大的候选值有哪些?
      1. 有可能该物品性价比极其低,那显然不选它可能是最好的,这样有可能最大值和次大值都为不放该物品对应的值;
      2. 有可能该物品的性价比超高,那显然选择它可能是最好的,这样有可能最大值和次大值都为放下该物品对应的值;
      3. 因此次大值的候选值会有 4 个:\(f[j][1], f[j][2], f[j-vi][1]+wi, f[j-vi][2]+wi\);
      4. 以此类推,针对每个容量,都会有 2k 个候选值。如果 \(f[j]\) 和 \(f[j-vi]\) 都存在 k 个不同值,那么 当前的 \(f[j]\) 肯定能够从中得到 k 个不同的值。
    • 另外一个问题就是如何选取 k 个不同值:
      1. 可以 sort 一遍再去重,简单粗暴有效
      2. 节俭归并排序中的合并,因为 \(f[j][k]\) 和 \(f[j-vi][k]+wi\) 都分别是降序序列,因此搞两个数组,从中不断取数合并在一起就可以了,代码略长,但是效率高不少

代码(归并的方法)

// 归并排序法合并两部分,取前kth个数
void bag() {
for (int i = 1; i <= n; ++i) {
for (int j = vol; j >= cost[i]; --j) {
int a[K] = {}, b[K] = {};
for (int k = 1; k <= kth; ++k) {
a[k] = dp[j][k];
b[k] = dp[j-cost[i]][k]+val[i];
}
a[kth+1] = -1;
b[kth+1] = -1; // 合并
int k = 1, x = 1, y = 1;
while (k <= kth && (x <= kth || y <= kth)) {
dp[j][k] = a[x] > b[y] ? a[x++] : b[y++];
if (dp[j][k] != dp[j][k-1]) {
k++;
}
}
}
}
printf("%d\n", dp[vol][kth]);
}

HDU - 2639 Bone Collector II 题解的更多相关文章

  1. HDU 2639 Bone Collector II(01背包变形【第K大最优解】)

    Bone Collector II Time Limit: 5000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others ...

  2. hdu 2639 Bone Collector II

    Bone Collector II Time Limit: 5000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others ...

  3. hdu 2639 Bone Collector II(01背包 第K大价值)

    Bone Collector II Time Limit: 5000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others ...

  4. HDU 2639 Bone Collector II (dp)

    题目链接 Problem Description The title of this problem is familiar,isn't it?yeah,if you had took part in ...

  5. HDU 2639 Bone Collector II【01背包 + 第K大价值】

    The title of this problem is familiar,isn't it?yeah,if you had took part in the "Rookie Cup&quo ...

  6. hdu 2639 Bone Collector II (01背包,求第k优解)

    这题和典型的01背包求最优解不同,是要求第k优解,所以,最直观的想法就是在01背包的基础上再增加一维表示第k大时的价值.具体思路见下面的参考链接,说的很详细 参考连接:http://laiba2004 ...

  7. HDU 2639 Bone Collector II(01背包变型)

    此题就是在01背包问题的基础上求所能获得的第K大的价值. 详细做法是加一维去推当前背包容量第0到K个价值,而这些价值则是由dp[j-w[ i ] ][0到k]和dp[ j ][0到k]得到的,事实上就 ...

  8. HDU - 2639 Bone Collector II (01背包第k大解)

    分析 \(dp[i][j][k]\)为枚举到前i个物品,容量为j的第k大解.则每一次状态转移都要对所有解进行排序选取前第k大的解.用两个数组\(vz1[],vz2[]\)分别记录所有的选择情况,并选择 ...

  9. HDU 2639 Bone Collector II (01背包,第k解)

    题意: 数据是常规的01背包,但是求的不是最大容量限制下的最佳解,而是第k佳解. 思路: 有两种解法: 1)网上普遍用的O(V*K*N). 2)先用常规01背包的方法求出背包容量限制下能装的最大价值m ...

随机推荐

  1. React实践相关

    语法高亮: sublime ctrl+shift+P 安装babel ,在view-syntax-open all width current extension as...-babel-js(bab ...

  2. 第七篇:wed版语音机器人

    wed版语音机器人: GitHub项目地址:https://github.com/Yang915/WebToy 特别说明:该项目在本机测试,通过浏览器调用系统麦克风(https请求),实际环境在Fir ...

  3. Redis-主从

    主从复制过程 1.从服务器开始连接主服务器时,会向主服务器发送一个SYNC同步命令 2.主服务器接收到命令后,执行BGSAVE,异步的将写命令保存到一个缓冲区里 3.主服务器执行完BGSAVE之后,就 ...

  4. 关于hadoop3.x MR报错:找不到或无法加载主类 org.apache.hadoop.mapreduce.v2.app.MRAppMaster

    用的apache Hadoop3.X,今天运行MR报错: 找不到或无法加载主类 org.apache.hadoop.mapreduce.v2.app.MRAppMaster 关键需要配置两个配置:ma ...

  5. Hyperledger Fabric Node SDK和应用开发

    Hyperledger Fabric 提供了多种语言的SDK版本,其中提出比较早.比较稳定而全面的是Node.js版本的SDK. 前面提到的fabric示例(如first-network和e2e-cl ...

  6. C++98/11/17表达式类别

    目标 以下代码能否编译通过,能否按照期望运行?(点击展开) #include <utility> #include <type_traits> namespace cpp98 ...

  7. SEPC:使用3D卷积从FPN中提取尺度不变特征,涨点神器 | CVPR 2020

    论文提出PConv为对特征金字塔进行3D卷积,配合特定的iBN进行正则化,能够有效地融合尺度间的内在关系,另外,论文提出SEPC,使用可变形卷积来适应实际特征间对应的不规律性,保持尺度均衡.PConv ...

  8. js数组对象的一些常用方法

    pop:删除数组最后一个元素 语法: array.pop(); 如 var array = ['1','2','3']; array.pop(); 返回结果:[‘1’,‘2’]此方法会改变数组的长度 ...

  9. UIAutomator2的API文档(三)

    1.UI对象识别器Selector 用法d(text='Clock', className='android.widget.TextView') 支持以下参数,详细信息可参考UiSelector Ja ...

  10. C#网络编程入门之UDP

    目录: C#网络编程入门系列包括三篇文章: (一)C#网络编程入门之UDP (二)C#网络编程入门之TCP (三)C#网络编程入门之HTTP 一.概述 UDP和TCP是网络通讯常用的两个传输协议,C# ...