背包问题进阶优雅总结【二维费用+分组+有依赖】

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/CQBZLYTina/article/details/81835017

目录

 

作者有话说

二维费用的背包问题

状态定义及转移

物品总个数的限制

小结

分组的背包问题

状态定义及转移

小结

有依赖的背包问题(重要)

分析

最后是非常不正经的ending


作者有话说

本篇博文中的各类数组都从1开始

题目里好像混进去了什么奇怪的东西

二维费用的背包问题

二维费用的背包问题是指:对于每件物品,具有两种不同的费用,选择这件物品必须同时付出这两种费用。对于每种费用都有一个可付出的最大值(背包容量)。问怎样 选择物品可以得到最大的价值。

设第 i 件物品所需的两种费用分别为 Ci 和 Di。两种费用可付出的最大值(也即两 种背包容量)分别为 V 和 U。物品的价值为 Wi。

状态定义及转移

cost增加了一位,那么状态定义时也要增加一位

定义dp[i][j][k]表示前i种物品费用为j和k时的最大价值

转移:\large dp[i][j][k]=max(dp[i-1][j][k],dp[i-1][j-c[i]][k-d[i]]+w[i])

同样,也可以滚成二维,根据物品类型更新,如若每件物品只有一件,注意要倒序。

物品总个数的限制

(来源:背包九讲)

很多时候,第二维的限制条件并不是直接给出的,而是需要转化,这也提示我们题目如果是在我们熟悉的基础上增加了一些限制条件,则可以从“陌生中找到熟悉”(这好像是我语文老师说的,不管了,要融会贯通),对现有的条件进行转化,然后根据模板切题(愉快地打板儿)

比如说 CF的Checkout Assistant 就是进行转化而来的,意识到可以偷物品就是买这件物品,可以“送”ti件物品,相当于花这件物品的money,可以得到ti+1件物品,而目标是得到n件物品,然后就是0-1背包板题。

小结

当发现由熟悉的动态规划题目变形得来的题目时,在原来的状态中加一维以满足新 的限制是一种比较通用的方法。

(来源:背包九讲)

分组的背包问题

有 N 件物品和一个容量为 V 的背包。第 i 件物品的费用是 Ci,价值是 Wi。这些物品被划分为 K 组,每组中的物品互相冲突,最多选一件。求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量,且价值总和最大。

状态定义及转移

这类问题的决策则要对于每组物品进行,对于每一组物品可以一个都不选,也可以选第1个、第2个、第3个······

则状态定义及转移也十分好想。定义dp[k][j]为前k组物品重量不超过j的最大价值

转移需要三层for:枚举组数、枚举重量、枚举组中的每一件物品。

\large dp[k][j]=max\begin{Bmatrix} dp[k-1][j],dp[k-1][j-v[i]]+w[i]| \in group k\end{Bmatrix}

小结

分组的背包问题将彼此互斥的若干物品称为一个组,这建立了一个很好的模型。不 少背包问题的变形都可以转化为分组的背包问题,由分组的背包问题进一步可 定义“泛化物品”的概念,十分有利于解题。

(来源:背包九讲)

有依赖的背包问题(重要)

这种背包问题的物品间存在某种“依赖”的关系。也就是说,物品 i 依赖于物品 j, 表示若选物品 i,则必须选物品 j。为了简化起见,我们先设没有某个物品既依赖于别 的物品,又被别的物品所依赖;另外,没有某件物品同时依赖多件物品。(否则就是树型dp)

分析

有依赖的背包问题来源于一道非常经典的题:金明的预算

但是这道题其实也有“巧”法 认真题的小朋友们会看到这样一句话:每个主件可以有 0个1 个或 2个附件

然后对于每一组物品(主件+附件)就有一下5种情况:

  1. 什么都不选
  2. 只选主件
  3. 主件+附件1
  4. 主件+附件2
  5. 主件+附件1+附件2

依次转移即可(定义dp[k][j] k表示前k组物品)


即使是上面的“巧”法,我们也用到了之前的分组背包的思想,如果不这么定义,状态将会很难表示,而且无法转移

现在考虑多个附件的情况

无疑,这样的策略是非常的,但是每一种策略都是互斥的(即不能同时选取多种策略)

我们可以对问题向分组背包进行如下转化:一个主件和它的附件集合对应分组背包中的一个物品组,每个选择了主件又选择了若干个附件的策略对应于这个物品组中的一个物品,其费用和价值都是这个策略中的物品的值的和

然而仅仅考虑到这一点是不够的,因为每一个物品组的物品数量十分地多(选了主件之后,每种附件可以选或不选,也可以直接就不选主件,所以物品数量等于决策数量,为\large 2^{n}+1),在数据过大的时候,时间会难以承受。

接下来,我们考虑优化。

对于第 k 个物品组中的 物品,所有费用相同的物品只留一个价值最大的,不影响结果。

所以,可以对主件 k 的 “附件集合”先进行一次 01 背包,得到费用依次为 0. . .V-Ck 所有这些值时相应的最大价值 f[0 . . . V-Ck]。

就相当于,我们把原来的那么多附件的物品的组合变成了V-Ck件重量分别为0. . .V-Ck,价值为f[0 . . . V-Ck]的物品,从而极大地减少了物品组中物品的数量。

然后,就可以优雅地用分组背包解决这个问题了。

或者我后面想到了另一种理解的思路

就是假设我们先选“主件”,然后选了主件之后附件就可以随便选,就用0-1背包做一下,然后就可以求出选了这个主件的最大价值

然后再一次更新,看这个物品组选不选(考虑连“主件”都不买的情况)

举一道例题

Consumer HDU - 3449

emmm...其实第一种思路是理解的背包九讲里面的东西 但是我没有打过这种思路的代码 不上手的话 其实还有点迷

如果有什么BUG的话,欢迎指正 悄悄溜走~~~


最后是非常不正经的ending

参考了《背包九讲》和网上一些资料,会在博文中标注,大多数部分为原创,请放心食用;由于作者水平有限,若有理解不到位或者表达有什么纰漏,可以 call me at [email protected] 或加qq请注明必要的信息+csdn

猜你喜欢

转载自blog.csdn.net/CQBZLYTina/article/details/81835017