博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
HDU 2639 Bone Collector II DP
阅读量:6116 次
发布时间:2019-06-21

本文共 2106 字,大约阅读时间需要 7 分钟。

首先相信你已经看过《背包九讲》。对于每一次决策后,我们都能得到一组值:F[ i,  j]   I 表示进行了i次决策,j表示占用了j 的体积。最终获得了F[i,j]的收益。这么考虑的话,很显然,就能得到最优子结构的性质

:如果最终能得到Fmax[ n, v ] ,那对于每一组i,j 必定 F[i,j]=Fmax[i,j]。因此,在遍历树的时候,如果两种决策有相同的i,j 那我们可以取出两者中的最大值,另外一种就被无情的抛弃了-_- 。这样,对于每一组的i,j 我们可以方便的按如下方程求出:

F[i,j]=max( F[i-1,j] , f[i-1][j-volume[i]]  + value[i] ) 按照这个方程,就能方便地求出最优解

 

再分析一下这个方程。他符合之前说的两种决策:选取物品i,或不选。最终的结果,是我们能在O(1)的时间内,判定对于体积j,是否应当选取第i件物品。 我们在这里作出了最优的选择。那被我们抛弃的选择呢?他很可能是次优解,第三优解,无论怎样,他都对我们本题求前K优解,起到了重要的作用!

那么,本题的算法,就水到渠成了。设数组[ i , j , p ]。表示对于一组 i,j,  F[i,j,p]  为其第P优的决策。那么,上文的max操作,就需要稍加扩展,变为对两个队列的合并(一种决策的第a1优解很可能是总体的第a2优解)。毋庸置疑,这两个队列是有序的,将其合并即可完成本次决策。代价,则从O(1) 涨到了O(k) ,总的时间复杂度由O(vn) 升至O(vnk) 刚好多了一维。RQNOJ上有前人写好的代码,可读性非常高,我就不贴我自己写的无比粗糙的代码了。

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

由于我们在选的时候把次优解已经丢掉了,其实次优解也可以和次优解可以合成次优解(这就是为什么不能丢掉次优解),这就是k循环的一个 的目的,再合并找出前k个最大的,为什么呢?(比喻以说明了)。

#include
#include
void ZeroOnePack( int N,int V, int K, int val[], int volumn[] ){ int f[1024][32]={0},A[32]={0},B[32]={0}; for( int i=1; i<= N; i++ ) { for( int j=V; j>=volumn[i]; j-- ) { int t=j-volumn[i]; for( int k=1;k<=K; k++ )//寻找体积j的前k个最优解合成的最优解 { A[k]=f[t][k]+val[i]; B[k]=f[j][k]; } int a=1,b=1,c=1; while( c<=K&&( a<=K||b<=K ) )//合并重新生成前k个最优解 { if( A[a]>B[b] ) f[j][c]=A[a],a++; else f[j][c]=B[b],b++; if( f[j][c]!=f[j][c-1] ) c++; } } } printf( "%d\n",f[V][K] ); }int main(){ int n,N,V,k,val[124],volumn[124]; scanf( "%d",&n ); for( int i=1; i<=n ; i++ ) { scanf( "%d%d%d",&N,&V,&k ); for( int j=1; j<=N; j++ ) scanf( "%d",&val[j] ); for( int j=1; j<=N; j++ ) scanf( "%d",&volumn[j] ); ZeroOnePack( N,V,k,val,volumn ); } return 0; }

  

转载于:https://www.cnblogs.com/bo-tao/archive/2011/08/13/2137506.html

你可能感兴趣的文章
java连接MySql数据库
查看>>
转:Vue keep-alive实践总结
查看>>
android studio修改新项目package名称
查看>>
深入python的set和dict
查看>>
C++ 11 lambda
查看>>
Hadoop2.5.0 搭建实录
查看>>
实验吧 recursive write up
查看>>
High-speed Charting Control--MFC绘制图表(折线图、饼图、柱形图)控件
查看>>
go test命令參数问题
查看>>
linux 搜索文本
查看>>
超实用Mac软件分享(二)
查看>>
Android JSON数据解析
查看>>
DEV实现日期时间效果
查看>>
java注解【转】
查看>>
Oracle表分区
查看>>
centos 下安装g++
查看>>
嵌入式,代码调试----GDB扫盲
查看>>
类斐波那契数列的奇妙性质
查看>>
配置设置[Django]引入模版之后报错Requested setting TEMPLATE_DEBUG, but settings are not configured....
查看>>
下一步工作分配
查看>>