背包问题动态规划

0-1背包

前提是你 提交于 2019-11-27 02:39:05
问题描述 : 给定n种物品和一背包,物品i的重量是wi,其价值为vi,背包的容量为C。问应如何选择装入背包的物品(物品不能分割),使得装入背包中物品的总价值最大? 抽象描述: x[n]:表示物品的选择,x[i]=1表示选择放进物品i到背包中。 问题分析: 1.抽象之后背包问题转换为找到一个最优的数组,x1,x2,.....,xn的0-1序列。 2.假设最优解的序列为x1,x2,.....,xn,能使背包容量C的总价值最大. 如果,x1=1,则x2,...,xn是C-w1容量的背包的总价值 依然是 最大的序列; 如果,x1=0,则x2,....,xn是C容量的背包的总价值 依然是 最大的序列。 这就是我们所说的最优子结构性质。 3.进一步分析:我们用m(i,j)表示为已经判断好了i:n的序列的背包最大价值,并且此时的背包剩余的容量为j,对物品i进行判断 如果j>wi, 就只要做出选择wi和不选择wi情况下,哪种更能使背包的总价值更大:m(i,j)=max{ m(i+1,j),m(i+1,j-wi)+vi} (注意这是个递归式) 如果j<wi: m(i,j)=m(i+1,j) 初始化: m(n,j)=vn (j>= wn); m(n,j)=0 (0<=j< wn) m(0,C)=0 最终的结果:m(1,C) 4.依次我们就得到了一个递归的表达式: 5.如果单纯的从利用递归

0-1背包问题(动态规划)

主宰稳场 提交于 2019-11-27 00:56:18
问题描述 n个物品和1个背包。对物品i,其价值为vi,重量为 wi,其价值为vi,背包容量为W。如何选取物品装入背包,使背包中所装入的物品的总价值最大? 数据结构的选择 数组w[n]来存放n个物品的重量; 数组v[n]来存放n个 物品的价值; 背包重量为W, 数组m[n+1][W+1]存放每次迭代执行结果; 数组x[n]用来存放所装入背包的物品状态 算法实现与测试 代码实现 package backpack ; import java . util . Scanner ; public class Backpack { /** * 动态规划算法实现 * @param v 存放n个 物品的价值数组 * @param w 存放n个物品的重量数组 * @param W 背包容量 * @param m 存放每次迭代执行结果 */ public static void knapsack ( int [ ] v , int [ ] w , int W , int [ ] [ ] m ) { int n = v . length ; //装入为0,初始化 for ( int i = 0 ; i < n + 1 ; i ++ ) m [ i ] [ 0 ] = 0 ; //背包内没有物品时初始化 for ( int j = 0 ; j < W + 1 ; j ++ ) m [ 0 ] [ j ]

背包问题的转化

廉价感情. 提交于 2019-11-26 23:52:28
转载自:https://www.lmlphp.com/user/56/article/item/4098/ 以上涉及的各种背包问题都是要求在背包容量(费用)的限制下求可以取到的最大价值,但背包问题还有很多种灵活的问法,在这里值得提一下。但是我认为,只要深入理解了求背包问题最大价值的方法,即使问法变化了,也是不难想出算法的。 例如,求解最多可以放多少件物品或者最多可以装满多少背包的空间。这都可以根据具体问题利用前面的方程求出所有状态的值(f数组)之后得到。 还有,如果要求的是“总价值最小”“总件数最小”,只需简单的将上面的状态转移方程中的max改成min即可。 下面说一些变化更大的问法。 输出方案 一般而言,背包问题是要求一个最优值,如果要求输出这个最优值的方案,可以参照一般动态规划问题输出方案的方法:记录下每个状态的最优值是由状态转移方程的哪一项推出来的,换句话说,记录下它是由哪一个策略推出来的。便可根据这条策略找到上一个状态,从上一个状态接着向前推即可。 还是以01背包为例,方程为 f[i][v]=max{f[i-1][v],f[i-1][v-c[i]]+w[i]} 再用一个数组g[i][v],设g[i][v]=0表示推出f[i][v]的值时是采用了方程的前一项(也即f[i][v]=f[i-1][v]),g[i][v]表示采用了方程的后一项。注意这两项分别表示了两种策略

动态规划之背包问题

白昼怎懂夜的黑 提交于 2019-11-26 19:24:41
动态规划之背包问题 01背包问题 问题1 为什么01背包问题可以用一维数组来优化? 问题2 使用一维数组优化过程中为什么物体的重量要从大到小枚举? code1 code2 code3 code(一维数组优化) 01背包问题 问题1 为什么01背包问题可以用一维数组来优化? 用二维数组枚举如下: 所以在枚举过程中仅用到上一行的数据,所以可以用一维数组来优化。 问题2 使用一维数组优化过程中为什么物体的重量要从大到小枚举? 我从大到小枚举如下: 我从小到大枚举如下: code1 #include<iostream> #define N 6 #define W 21 int B[N][W] = { 0 }; int w[6] = { 0, 2, 3, 4, 5, 9 }; int v[6] = { 0, 3, 4, 5, 8, 10 }; void knapsack() { int k, C; for (k = 1; k < N; k++) { for (C = 1; C < W; C++) { if (w[k] > C) { B[k][C] = B[k - 1][C]; } else { int value1 = B[k - 1][C - w[k]] + v[k]; int value2 = B[k - 1][C]; if (value1 > value2) { B[k][C] =

动态规划总结

空扰寡人 提交于 2019-11-26 17:42:43
背包问题一直是动态规划的热点,也是各大公司笔试的常客,所以掌握基本的背包解题思路是很重要的 0-1 背包问题 题目 有 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]) 这个方程非常重要,基本上所有跟背包相关的问题的方程都是由它衍生出来的。 “将前 i 件物品放入容量为 v 的背包中”这个子问题,若只考虑第 i 件物品的策略(放或不放),那么就可以转化为一个只牵扯前 i-1 件物品的问题。 f[i - 1][v] 如果不放第 i 件物品,那么问题就转化为“前 i-1 件物品放入容量为 v 的背包中”,价值为 f[i-1][v] f[i - 1][v - c[i]] + w[i] 如果放第 i 件物品,那么问题就转化为“前 i-1 件物品放入剩下的容量为 v-c[i] 的背包中”,此时能获得的最大价值就是 f[i-1][v-c[i]] 再加上通过放入第i件物品获得的价值 w[i] 。

动态规划——01背包问题

泄露秘密 提交于 2019-11-26 16:54:37
01背包问题 背包问题是著名的 NP完全问题 ,在实际生活中有广泛的应用。01背包是背包问题中的一种,也是较简单的一种,利用动态规划的思想可以寻求01背包的解。 问题描述 设有n个物品,他们具有各自的重量w和价值v;给定一个具有一个容量W的背包,求将物品有选择的放入背包中,使得装入的物品的价值之和最大? 01背包 :物品是完整个体,只存在 放或不放 两种状态,不能放入一部分。 分析设计 动态规划求解问题需要找到可分解的大问题,将问题不断划分为子问题就可以求解,通过一个二维数组构成的表的形式记录子问题,最终大问题的解也可以求解出来。 01背包问题中的子问题是什么? 更少的物品:当只有0件物品时,答案就很明显了,不用放; 更小的背包:当背包的容量为0时,答案就很明显了,放不了。 因此构建二维数组 K ( n , W ) K(n,W) K ( n , W ) ,其中 K ( i , j ) K(i,j) K ( i , j ) 表示:当前背包容量为j,物品有前i个可以放,此时的背包问题的。 只要我们能找到一个递推关系,能使我们从 K ( 0 , 0 ) K(0,0) K ( 0 , 0 ) 算到 K ( n , W ) K(n,W) K ( n , W ) 即可, K ( n , W ) K(n,W) K ( n , W ) 就是整个大问题的解。 对于求 K ( i , j ) K(i

清北学堂dp图论营游记day2

时光怂恿深爱的人放手 提交于 2019-11-26 12:03:13
上午讲数位dp和背包问题。 先讲背包: 完全背包:换了个顺序: 多重背包: 多重背包优化: 这样把每个物品分成这些组,那么把他们转变成不同的物品,就变成了01背包问题; 滑动窗口取最值问题。单调队列优化。 方法很简单,枚举每一组中的其中一个物品计算即可。 小技巧: 有些懵。。。 : 终于,到了数位dp环节:(恶心了一上午。) dp方法: 判断上界。 假如我们要枚举到2147,当前已经枚举到了第二位,如果枚举到了1,那么我们说他达到了上界,下一位只能从0枚举到4。如果这一位是0,由于不管下一位是多少,这个数永远不可能大于原数,那么可以从0到9任意枚举。后几位也是如此。 下午: 接着讲树形dp: 前言 1:与树或图的生成树相关的动态规划。 2:以每棵子树为子结构,在父亲节点合并,注意树具有天然的子结构。 这是很优美的很利于dp的。 3:巧妙利用Bfs或Dfs序,可以优化问题,或得到好的解决方法。 4:可以与树上的数据结构相结合。 5:树形Dp的时间复杂度要认真计算,部分问题可以均摊复杂度分析。 6:一般设f[u]表示u子树的最优价值或者是说方案数。 或者f[u][k]表示u子树附加信息为k的最优值,往往是通过考虑子树根节点 的情况进行转移。 第一题: 完结 来源: https://www.cnblogs.com/lbssxz/p/11318909.html