Processing math: 100%

问答详情

个人中心

程序设计竞赛背包问题—完全背包

2016-02-07 浏览 2491 关注 0

引言

本节将结合完全背包问题,介绍动态规划中基础的的优化方法。

基本模型

现要把N种物品装进一个大小为M的背包,第i种物品大小为w[i],价值为v[i],每种物品有任意多个。那么这个背包能装下物品的最大价值是多少?

模型分析

完全背包与多重背包不同之处在于每种物品有任意多个,而多重背包每种物品有数量限制。当然,我们可以完全按照多重背包的方法来做。每次做决策时,虽然没有了a[i]的数量限制,但因为背包大小有限,使用第i种物品的数量自然也不可能无限增长下去。

我们先来回顾一下多重背包状态转移方程:

f(i,j)=maxa[i]k=0{v[i]k+f(i1,jw[i]k)jw[i]k}

而完全背包的状态转移方程,只要把a[i]的限制换成+∞即可。因为要满足jw[i]k,所以k严格意义上的上界是jw[i]

所有可以得到完全背包的状态转移方程:

f(i,j)=maxjw[i]k=0{v[i]k+f(i1,jw[i]k)}

这个算法的时间复杂度仍然是O(nm2),因为决策不再受a[i]限制,所以该算法的计算次数一定不会比多重背包少。但是完全背包问题与多重背包相比少了很多的限制条件,问题更加一般化,直观上的感受性质也会更好一些。然而使用原先的方法,却只能算的更慢(虽然复杂度并没有变化),所以很可能存在着更快的算法等着我们来发现。

优化方法

动态规划的复杂度主要是两个方面,一个是状态的规模,一个是转移时枚举决策的复杂度。作为基础动态规划篇的前几节,这里就不深入介绍,如何确定该使用哪一种优化技巧,而是直接把这种优化方法当做一个典例介绍给大家。

在多重背包问题中,我们尝试对转移环节进行优化。原算法的复杂度O(nm2)中的最后一个m,就是源于决策最坏情况下会达到O(m)级别。我们原来的分析方法是,用前i种物品去填充大小为j的背包,枚举第i种物品使用了多少个。然而我们可以换一种想法,决策变为是否填一个第i种物品。

如果填一个第i种物品,那么获得价值v[i],背包剩余空间j-w[i]。因为每种物品都有无限个,所以接下来仍然可以随便使用第i种物品。于是接下来的问题就变为用前i种物品,填充大小为j-w[i]的背包,最大价值是多少。仍然是用前i种物品,只不过背包大小有所减少。

f(i,j)=v[i]+f(i,jw[i])jw[i]

如果第i种物品不用了,接下来就要用前i-1种物品填充大小为j的背包了。

f(i,j)=f(i1,j)

综合以上两种情况,就可以得到新的状态转移方程:

f(i,j)=max{v[i]+f(i,jw[i])jw[i]f(i1,j)

状态的规模仍然为O(n*m),不过现在的决策只有两种,转移的复杂度为O(1),所以整体的时间复杂度为O(nm)

为什么这一算法会比原算法快呢?关键就在于这个f(i,j-w[i]),原先此处还要继续比较用2,3,4...件第i种物品的最大价值,而现在只用一个f(i,j-w[i])就解决了所有问题。事实上是因为所有这些情况在f(i,j-w[i])中已经被计算过了。

在原先的算法中,计算f(i,j)、f(i,j-w[i])、f(i,j-2*w[i])...时,都只是利用f(i-1,...)来计算,但是其中包含了大量重复性的比较。而现在直接用f(i,j-w[i])来计算f(i,j),就省去了这些重复性的工作,提高了算法的整体效率。

在理解了该算法的基础上,读者不妨思考一下,为什么不能对多重背包问题也使用这种优化方法?

具体实现

现在每一个状态f(i,j)不仅依赖于f(i-1,j),还依赖于f(i,j-w[i])。所以我们不妨在两个维度都按照从小到大的顺序来求解。

核心代码

for(j=0;j<=m;j++) f[0][j]=0;
for(i=1;i<=n;i++)
       for(j=0;j<=m;j++)
       {
              f[i][j]=f[i-1][j];
              if(j>=w[i])
              {
                     tmp=v[i]+f[i][j-w[i]];
                     if(tmp>f[i][j]) f[i][j]=tmp;
              }
       }//f[n][m] is the answer

该算法实现和01背包的实现其实只有一处不同,你发现了么?

written by PCZ

问答发起人 王瑞康 王瑞康 山东大学

全部回答(0)

还木有回答哦,快抢占第一把交椅吧!

- 查看更多和回答问题请下载赛氪APP -
赛乐云AI 证书查询
取消 确认

同学~下载赛氪APP就可以进群咯~
先不聊 去下载