ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

背包九讲

2019-08-10 16:02:19  阅读:328  来源: 互联网

标签:费用 件物品 cost .. 九讲 背包 物品


目录

  • 01背包问题
  • 完全背包问题
  • 多重背包问题
  • 混合三种背包问题
  • 二维费用的背包问题
  • 分组的背包问题
  • 有依赖的背包问题
  • 泛化物品
  • 背包问题问法的变化

01背包问题

基本问题

有 \(N\) 件物品和一个容量为 \(V\) 的背包。第 \(i\) 件物品的费用是 \(c[i]\),价值是 \(w[i]\)。求解将哪些物品装入背包可使价值总和最大。

基本思路

\(f[i][v]\) 表示前 \(i\) 件物品恰放入一个容量为 \(v\) 的背包可以获得的最大价值。则其状态转移方程便是:

\[ f[i][v]=max(f[i-1][v], f[i-1][v-c[i]]+w[i]) \]

\(f[N][V]\) 则为背包可能的最大价值。

优化空间复杂度

时间复杂度为\(O(N\times V)\),空间复杂度可以优化为\(O(V)\)。

for i = 1..N
    for v = V..0
        f[v] = max{f[v], f[v - c[i]] + w[i]};

初始化的细节问题

  • 要求恰好装满背包:\(f[0]\) 设置为0,其他\(f[1..V]\) 均设置为 \(- \infty\)。
  • 不要求恰好装满背包,只要求价值最大:\(f[0..V]\)均设置为0。

题目

HDU2602题解

完全背包问题

基本问题

有 \(N\) 种物品和一个容量为 \(V\) 的背包,每种物品都有无限件可用。第 \(i\) 种物品的费用是 \(c[i]\),价值是\(w[i]\)。求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量,且价值总和最大。

基本思路

令 \(f[i][v]\) 表示前 \(i\) 种物品恰放入一个容量为 \(v\) 的背包的最大权值。可以得到状态转移方程式:

\[ f[i][v]=max(f[i - 1][v - k \times c[i]] + k \times w[i] | 0 <= k \times c[i] <= v) \]

改进做法

我们可以通过一个 \(O(N\times V)\) 的方法进行完全背包问题求解。状态转移方程式为:

\[ f[i][v]=max(f[i-1][v], f[i][v-c[i]]+w[i]) \]

\(f[V]\) 则为背包可能的最大价值。

for i = 1..N
    for v = 0..V
        f[v] = max{f[v], f[v - cost] + weight}

题目

HDU1114题解

多重背包问题

基本问题

有 \(N\) 种物品和一个容量为 \(V\) 的背包。第 \(i\) 种物品最多有 \(n[i]\)件可用,每件费用是 \(c[i]\),价值是 \(w[i]\)。求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量,且价值总和最大。

基本思路

令 \(f[i][v]\) 表示前 \(i\) 种物品恰放入一个容量为 \(v\) 的背包的最大权值,则有状态转移方程:

\[ f[i][v]=max(f[i-1][v-k \times c[i]]+k\times w[i]|0<=k<=n[i]) \]

复杂度为 \(O(V \times \sum_i n[i])\)。

二进制优化

将第 \(i\) 种物品分成若干件物品,其中每件物品有一个系数,这件物品的费用和价值均是原来的费用和价值乘以这个系数。使这些系数分别为 \(1,2,4,...,2^{k-1}, n[i] - 2^{k+1}\),且 \(k\) 是满足 \(n[i] - 2^{k+1} > 0\) 的最大整数。例如:如果 \(n[i]\) 为 \(13\),就将这种物品分成系数分别为 \(1,2,4,6\) 的四件物品。

这样就将第 \(i\) 种物品分成了 \(O(\log n[i])\) 种物品,将原问题转化为了复杂度为 \(O(V\times \sum \log n[i])\) 的 01 背包问题

procedure ZeroOnePack(cost, weight)
    for v = V..cost
        f[v] = max{f[v], f[v - cost] + weight}
 
procedure CompletePack(cost, weight)
    for v = cost..V
        f[v] = max{f[v], f[v - cost] + weight}

procedure MultiplePack(cost, weight, amount)
    if cost * amount >= V {
        CompletePack(cost, weight)
        Return
    }
    integer k = 1
    while k < amount {
        ZeroOnePack(k * cost, k * weight)
        amount = amount - k
        k = k * 2
    }
    ZeroOnePack(amount * cost, amount * weight)

单调队列优化

基于基本算法的状态转移方程,应用单调队列的方法使每个状态的值可以以均摊 \(O(1)\) 的时间求解。总的复杂度可以达到 \(O(NV)\)

参考

题目

HDU1059题解

混合三种背包问题

基本问题

有的物品只可以取一次(01 背包),有的物品可以取无限次(完全背包),有的物品可以取的次数有一个上限(多重背包)。即将前三种情况混合起来。求解背包可能的最大价值。

基本思路

混合使用以上的三种背包问题求解方法。

for i = 1..N
    if 第 i 件物品是 01 背包
        ZeroOnePack(c[i], w[i])
    else if 第 i 件物品是完全背包
        CompletePack(c[i], w[i])
    else if 第 i 件物品是多重背包
        MultiplePack(c[i], w[i], n[i])

二维费用的背包问题

基本问题

对于每件物品,具有两种不同的费用;选择这件物品必须同时付出这两种代价;对于每种代价都有一个可付出的最大值(背包容量)。问怎样选择物品可以得到最大的价值。设这两种代价分别为 代价 1 代价 2 ,第 \(i\) 件物品所需的两种代价分别为 \(a[i]\) 和 \(b[i]\)。两种代价可付出的最大值(两种背包容量)分别为 \(V\) 和 \(U\)。物品的价值为 \(w[i]\)。

基本思路

设 \(f[i][v][u]\) 表示前 \(i\) 件物品付出两种代价分别为 \(v\) 和 \(u\) 时可获得的最大价值。状态转移方程为:

\[ f[i][v][u] = max(f[i-1][v][u], f[i-1][v-a[i]][u-b[i]] + w[i]) \]

物品个数限制

有时,“二维费用”的条件是以这样一种隐含的方式给出的:最多只能取 \(M\) 件物品。这事实上相当于每件物品多了一种“件数”的费用,每个物品的件数费用均为 \(1\),可以付出的最大件数费用为 \(M\)。

设 \(f[v][m]\) 表示付出费用 \(v\)、最多选 \(m\) 件时可得到的最大价值,则根据物品的类型(01、完全、多重)用不同的方法循环更新,最后在 \(f[0..V][0..M]\) 范围内寻找答案

分组的背包问题

基本问题

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

基本思路

\(f[k][v]\) 表示前 \(k\) 组物品花费费用 \(v\) 能取得的最大权值,则有:

\[ f[k][v] = max(f[k-1][v], f[k-1][v - c[i]] + w[i] | 物品 i 属于第 k 组) \]

伪代码如下。注意三层 for 循环的顺序不能写错。

for 所有的组 k
    for v = V..0
        for 所有的 i 属于组 k
            f[v] = max{f[v], f[v - c[i]] + w[i]}

有依赖的背包问题

基本问题

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

基本思路

我们可以对主件 \(i\) 的“附件集合”先进行一次 01 背包,得到费用依次为 \(0..V-c[i]\)所有这些值时相应的最大价值 \(f'[0..V-c[i]]\)。那么这个主件及它的附件集合相当于 \(V-c[i]+1\) 个物品的物品组,其中费用为 \(c[i]+k\) 的物品的价值为 \(f'[k]+w[i]\)。也就是说原来指数级的策略中有很多策略都是冗余的,通过一次 01 背包后,将主件 \(i\) 转化为 \(V-c[i]+1\) 个物品的物品组,就可以直接应用分组背包问题 =的算法解决问题了。

泛化物品

泛化物品的定义

考虑这样一种物品,它并没有固定的费用和价值,而是它的价值随着你分配给它
的费用而变化。这就是泛化物品的概念。

更严格的定义是:在背包容量为 \(V\) 的背包问题中,泛化物品是一个定义域为 \(0..V\)
中的整数的函数 \(h\),当分配给它的费用为 \(v\) 时,能得到的价值就是 \(h(v)\)。

标签:费用,件物品,cost,..,九讲,背包,物品
来源: https://www.cnblogs.com/solvit/p/11331860.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有