初学背包。以下内容,来源网络,整理以作学习资料。

求第K优解

对于求次优解、第K优解类的问题,如果相应的最优解问题能写出状态转移方程、用动态规划解决,那么求次优解往往可以相同的复杂度解决,第K优解则比求最优解的复杂度上多一个系数K。其基本思想是将每个状态都表示成有序队列,将状态转移方程中的max/min转化成有序队列的合并。这里仍然以01背包为例讲解一下。首先看01背包求最优解的状态转移方程:f[i][v]=max{f[i-1][v],f[i-1][v-c[i]]+w[i]}。如果要求第K优解,那么状态f[i][v]就应该是一个大小为K的数组f[i][v][1..K]。其中f[i][v][k]表示前i个物品、背包大小为 v时,第k优解的值。“f[i][v]是一个大小为K的数组”这一句,熟悉C语言的同学可能比较好理解,或者也可以简单地理解为在原来的方程中加了一维。 显然f[i][v][1..K]这K个数是由大到小排列的,所以我们把它认为是一个有序队列。然后原方程就可以解释为:f[i][v]这个有序队列是由f[i-1][v]和f[i-1][v-c[i]]+w[i]这两个有序队列合并得到的。有序队列f[i-1][v]即f[i-1][v][1..K],f[i-1][v-c[i]]+w[i]则理解为在f[i-1][v-c[i]] [1..K]的每个数上加上w[i]后得到的有序队列。合并这两个有序队列并将结果的前K项储存到f[i][v][1..K]中的复杂度是O(K)。最后的答案是f[N][V][K]。总的复杂度是O(VNK)。

为什么这个方法正确呢?实际上,一个正确的状态转移方程的求解过程遍历了所有可用的策略,也就覆盖了问题的所有方案。只不过由于是求最优解,所以其 它在任何一个策略上达不到最优的方案都被忽略了。如果把每个状态表示成一个大小为K的数组,并在这个数组中有序的保存该状态可取到的前K个最优值。那么, 对于任两个状态的max运算等价于两个由大到小的有序队列的合并。另外还要注意题目对于“第K优解”的定义,将策略不同但权值相同的两个方案是看作同一个解还是不同的解。如果是前者,则维护有序队列时要保证队列里的数没有重复的。

用个形象的比喻吧:如果我想知道学年最高分,那么,我只要知道每个班级的最高分,然后统计一遍就可以了。如果我想知道学年前十呢?我必须要知道每个班的前十名。大家在心里模拟一下,对,这就是本题核心的算法。两种决策,就可以看作这个学年只有两个班。

AC代码:

#include<iostream>
using namespace std;
int n,vol,k;
int dp[1005][35],value[105],cost[105],A[35],B[35];
void kth_ZeroOnePack()
{
memset(dp,0,sizeof(dp));
int i,j,kk,a,b,c;
for(i=1;i<=n;++i)
{
for(j=vol;j>=cost[i];--j)
{
for(kk=1;kk<=k;++kk)
{
A[kk]=dp[j-cost[i]][kk]+value[i];
B[kk]=dp[j][kk];
}
A[kk]=B[kk]=-1;
a=b=c=1;
while(c<=k && (A[a]!=-1 || B[b]!=-1))
{
if(A[a]>B[b])
dp[j][c]=A[a],++a;
else
dp[j][c]=B[b],++b;
if(dp[j][c]!=dp[j][c-1])
++c;
}
}
}
cout<<dp[vol][k]<<endl;
}
int main()
{
int tCase;
cin>>tCase;
while(tCase--)
{
cin>>n>>vol>>k;
for(int i=1;i<=n;++i)
cin>>value[i];
for(int j=1;j<=n;++j)
cin>>cost[j];
kth_ZeroOnePack();
}
return 0;
}

HDU2639 01背包 第K优决策相关推荐

  1. HDU 2639 Bone Collector II(01背包-第K优决策)

    Description 给出n件物品的价值和体积,问在总体积不超过v时的第k大价值 Input 第一行为用例组数T,每组用例第一行为三个整数n,v和k,第二行n个整数表示这n件物品的价值,第三行n个整 ...

  2. 【01背包的k值问题 HDU2639 HDU2126】

    HDU2639 有深度吧感觉还 题意:给出一行价值,一行体积,让你在v体积的范围内找出第k大的值 终结第k大的01背包, 复杂度: O(NMK) 注意选取的标准,选取后,要保证得到的价值是大于未选之前 ...

  3. 第K优决策 HDU2639

    看到一些比较好的东西,感觉对理解这个对于求次优解.第K优解类的问题非常有启发性吧,以前不知道应该怎么办,看了以后感觉稍微有点点想法,多想想吧,估计能触类旁通,遇到相关的一些题目可能也会有一定的想法吧, ...

  4. hdu2639,第K优决策

    在dp问题中如果遇到问题,没有什么是加一维度不能解决的,如果不能,再加一维度. #include<iostream> #include<cstring> #include< ...

  5. 01背包经典例题详解

    转载自点击打开链接 首先01背包题目的雏形是 有N件物品和一个容量为V的背包.第i件物品的费用是c[i],价值是w[i].求解将哪些物品装入背包可使价值总和最大. 从这个题目中可以看出,01背包的特点 ...

  6. 【背包专题】01背包

    暑假集训开始了,按照队里的分配,我是弄DP的,嘛,于是我又一次的开始了从01背包开始学习,昨天将杭电的几道01背包重新做了一遍,下面讲讲我自己对于01背包的理解. 首先01背包题目的雏形是 有N件物品 ...

  7. hdu 6092 Rikka with Subset 01背包 思维

    dp[i][j]表示前i个元素,子集和为j的个数.d[i][j] = d[i][j] + d[i-1][j-k] (第i个元素的值为k).这里可以优化成一维数组 比如序列为 1 2 3,每一步的dp值 ...

  8. 2639-Bone Collector II (01背包之第k优解)

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=2639 求第k优解的关键代码: 用两个数组记录两种状态(选择或不选择),并且只要记录前k次.在这两个数 ...

  9. HDU 2639(01背包求第K大值)

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=2639 Bone Collector II Time Limit: 5000/2000 MS (Jav ...

最新文章

  1. linux下文件的压缩和解压缩
  2. EASYHOOK逆向寒假生涯(20/100)
  3. uvalive4840(n*n方阵的最小花费)
  4. c语言中stdbool.h的使用
  5. 基础提供程序在 Open 上失败
  6. javaScript中const,var,let区别与用法详解
  7. 5g理论速度_华为5G随行WiFi Pro 有多强 我们试一下NSA网络下的5G速度
  8. SQLServer启动和关闭bat脚本
  9. springboot整合sentinel
  10. oracle同音字模糊查询,已释甲骨文会意字研究.pdf
  11. Python实现词云图的3种方式(词频,一段文本,自定义样式)
  12. 理论+示例,三个问题系统捋清UGC平台的玩法
  13. C# 使用斑马打印机打印图片
  14. HDU 6438 Buy and Resell
  15. 数字兆欧表的使用及安全注意事项
  16. token验证的方法
  17. 【技术类】Landsat 7 ETM+影像条带去除妙招
  18. Python基础知识梳理
  19. 基于PHP美食食谱的外文翻译,中国传统菜谱的英文翻译锦集
  20. arm服务器测评_某ARM服务器与X86服务器简单性能对比

热门文章

  1. 安全编程基础——Cppcheck工具的入门学习
  2. R语言使用dplyr包的arrange函数依据dataframe数据的指定数据列对dataframe进行排序(默认从小到大)
  3. 基于springboot实现茶室客户自带茶品管理系统演示【附项目源码+论文说明】
  4. android动态壁纸2.2.1,8.2.1启动动态壁纸的方法
  5. 然而由于1-6全部发在《IT外企那点儿事(1):外企也就那么回事》
  6. 真的是quot;关心quot;?请别传递…
  7. Python 正则式学习笔记
  8. eclipse调试tomcat
  9. 免费自定义txt背单词APP(其它科目也可以)
  10. Python类中的self是什么意思?