背包问题解法
- 格式:doc
- 大小:111.50 KB
- 文档页数:17
01背包问题,是用来介绍动态规划算法最经典的例子,网上关于01背包问题的讲解也很多,我写这篇文章力争做到用最简单的方式,最少的公式把01背包问题讲解透彻。
01背包的状态转换方程f[i,j] = Max{ f[i-1,j-Wi]+Pi( j >= Wi ), f[i-1,j] }f[i,j]表示在前i件物品中选择若干件放在承重为j 的背包中,可以取得的最大价值。
Pi表示第i件物品的价值。
决策:为了背包中物品总价值最大化,第i件物品应该放入背包中吗?题目描述:有编号分别为a,b,c,d,e的五件物品,它们的重量分别是2,2,6,5,4,它们的价值分别是6,3,5,4,6,现在给你个承重为10的背包,如何让背包里装入的物品具有最首先要明确这张表是从右到左,至底向上生成的。
为了叙述方便,用e10单元格表示e行10列的单元格,这个单元格的意义是用来表示只有物品e时,有个承重为10的背包,那么这个背包的最大价值是6,因为e物品的重量是4,背包装的了,把e装进去后价值为6。
然后是e9单元格表示背包承重9,只有物品e, e装进去后,背包价值为6,接着是e8, e7单元格,一直到e3单元格表示背包承重3,但物品e承重4,装不了,所以e3=0,对于d10单元格,表示只有物品e,d时,承重为10的背包,所能装入的最大价值,是10,因为物品e,d这个背包都能装进去。
对于承重为9的背包,d9=10,是怎么得出的呢?根据01背包的状态转换方程,需要考察两个值,一个是f[i-1,j],对于这个例子来说就是e9的值6,另一个是f[i-1,j-Wi]+Pi;在这里,f[i-1,j]表示我有一个承重为9的背包,当只有物品e可选时,这个背包能装入的最大价值f[i-1,j-Wi]表示我有一个承重为4的背包(等于当前背包承重减去物品d的重量),当只有物品e可选时,这个背包能装入的最大价值f[i-1,j-Wi]就是指单元格e4值为6,Pi指的是d物品的价值,即4由于f[i-1,j-Wi]+Pi = 6 + 4 = 10 大于f[i-1,j] = 6,所以物品d应该放入承重为9的背包,所以d9=10.。
P01: 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]}这个方程非常重要,基本上所有跟背包相关的问题的方程都是由它衍生出来的。
所以有必要将它详细解释一下:“将前i件物品放入容量为v的背包中”这个子问题,若只考虑第i件物品的策略(放或不放),那么就可以转化为一个只牵扯前i-1件物品的问题。
如果不放第i件物品,那么问题就转化为“前i-1件物品放入容量为v的背包中”,价值为f[i-1][v];如果放第i件物品,那么问题就转化为“前i-1件物品放入剩下的容量为v-c[i]的背包中”,此时能获得的最大价值就是f[i-1][v-c[i]]再加上通过放入第i件物品获得的价值w[i]。
优化空间复杂度以上方法的时间和空间复杂度均为O(VN),其中时间复杂度应该已经不能再优化了,但空间复杂度却可以优化到O。
先考虑上面讲的基本思路如何实现,肯定是有一个主循环i=1..N,每次算出来二维数组f[i][0..V]的所有值。
那么,如果只用一个数组f[0..V],能不能保证第i次循环结束后f[v]中表示的就是我们定义的状态f[i][v]呢?f[i][v]是由f[i-1][v]和f[i-1][v-c[i]]两个子问题递推而来,能否保证在推f[i][v]时(也即在第i次主循环中推f[v]时)能够得到f[i-1][v]和f[i-1][v-c[i]]的值呢?事实上,这要求在每次主循环中我们以v=V..0的顺序推f[v],这样才能保证推f[v]时f[v-c[i]]保存的是状态f[i-1][v-c[i]]的值。
一个最优解:w i X i Wi2w1X1nmaX v i X i 。
如果不是的话,设(y2,y3, , y n) 是这X i {0,1}( 2 i n) i2问题描述0/1 背包问题 :现有n种物品,对1<=i<=n ,已知第i种物品的重量为正整数 W i,价值为正整数 V i, 背包能承受的最大载重量为正整数W,现要求找出这n种物品的一个子集,使得子集中物品的总重量不超过 W 且总价值尽量大。
(注意:这里对每种物品或者全取或者一点都不取,不允许只取一部分)算法分析根据问题描述,可以将其转化为如下的约束条件和目标函数:n w i x i Wi 1i i(1)x i { 0,1}( 1 i n)nmax v i x i (2)i1于是,问题就归结为寻找一个满足约束条件( 1 ),并使目标函数式( 2 )达到最大的解向量X (x1, x2 ,x3, ......... , x n) 。
首先说明一下 0-1 背包问题拥有最优解。
假设(X i,X2,X3,……,Xn)是所给的问题的一个最优解,则(X2,X3,……,Xn)是下面问题的n n n个问题的一个最优解,则v i y i v i X i ,且w1X1 w i y i W 。
因此,i 2 i 2 i 2n n n物品1W2=3V2=12物品2W3=4V3=40物品3W4=5V4=25物品4V1X1 V i y i V1X1 V i V i X i,这说明(X i,y2,y3, ............................................................... ,y n)是所给的 0-1 背包问i 2 i 2 i 1题比(X i,X2,X3, ........................... , X n)更优的解,从而与假设矛盾。
穷举法:用穷举法解决0-1背包问题,需要考虑给定 n个物品集合的所有子集,找出所有可能的子集(总重量不超过背包重量的子集) ,计算每个子集的总重量,然后在他们中找到价值最大的子集。
分支界限方法是一种用于解决优化问题的算法。
在动态规划算法中,分支界限方法被广泛应用于解决01背包问题。
01背包问题是一个经典的动态规划问题,其解题步骤如下:1. 确定问题:首先需要明确01背包问题的具体描述,即给定一组物品和一个背包,每个物品有自己的价值和重量,要求在不超过背包容量的情况下,选取尽可能多的物品放入背包,使得背包中物品的总价值最大。
2. 列出状态转移方程:对于01背包问题,可以通过列出状态转移方程来描述问题的求解过程。
假设dp[i][j]表示在前i个物品中,背包容量为j时能够获得的最大价值,则状态转移方程可以表示为:dp[i][j] = max(dp[i-1][j], dp[i-1][j-w[i]]+v[i])3. 初始化边界条件:在动态规划中,需要对状态转移方程进行初始化,一般情况下,dp数组的第一行和第一列需要单独处理。
对于01背包问题,可以初始化dp数组的第一行和第一列为0。
4. 利用分支界限方法优化:针对01背包问题,可以使用分支界限方法来优化动态规划算法的效率。
分支界限方法采用广度优先搜索的思想,在每一步选择最有希望的分支,从而减少搜索空间,提高算法的效率。
5. 实际解题步骤:根据上述步骤,实际解决01背包问题的步骤可以概括为:确定问题,列出状态转移方程,初始化边界条件,利用分支界限方法优化,最终得到问题的最优解。
分支界限方法在解决01背包问题时起到了重要的作用,通过合理的剪枝策略,可以有效地减少动态规划算法的时间复杂度,提高问题的求解效率。
分支界限方法也可以应用于其他优化问题的求解过程中,在算法设计和实现中具有重要的理论和实际意义。
在实际应用中,分支界限方法需要根据具体问题进行灵活选择和调整,结合动态规划和剪枝策略,以便更好地解决各类优化问题。
掌握分支界限方法对于解决复杂问题具有重要的意义,也是算法设计和优化的关键技术之一。
分支界限方法在解决01背包问题的过程中,具有重要的作用。
背包问题是一种经典的优化问题,通常用于解决在给定一组物品和它们的重量、价值等信息的情况下,如何选择一些物品放入一个容量有限的背包中,使得背包中物品的总价值最大或总重量最小等问题。
以下是背包问题的一种经典算法——动态规划法:
1. 定义状态:设f[i][j]表示前i个物品中选择若干个物品放入容量为j的背包中所能获得的最大价值或最小重量。
2. 状态转移方程:对于第i个物品,有两种情况:
- 不放入背包中,此时f[i][j]=f[i-1][j];
- 放入背包中,此时f[i][j]=max(f[i-1][j], f[i-1][j-w[i]]+v[i]),其中w[i]和v[i]分别表示第i 个物品的重量和价值。
3. 初始化:f[0][0]=0。
4. 计算最优解:根据状态转移方程,从上到下依次计算每个物品的状态值,最终得到f[n][m]即为所求的最优解。
时间复杂度:O(n*m),其中n为物品数量,m为背包容量。
空间复杂度:O(n*m)。
背包问题的数学模型摘要:1.背包问题的定义2.背包问题的数学模型3.背包问题的求解方法4.背包问题的应用实例正文:一、背包问题的定义背包问题是一个经典的优化问题,它的问题是给定一个背包和n 种物品,其中,背包的容量为V,第i 种物品的质量为c_i,价值为p_i,如何通过物品选择,使得装入背包中的物品总价值最大。
二、背包问题的数学模型为了更好地理解背包问题,我们可以将其建立一个数学模型。
假设有n 种物品,分别用v_i 表示第i 种物品的价值,c_i 表示第i 种物品的质量,那么背包问题的数学模型可以表示为:f(x) = max {v_1x_1 + v_2x_2 +...+ v_nx_n}s.t.c_1x_1 + c_2x_2 +...+ c_nx_n <= Vx_i >= 0, i = 1,2,...,n其中,f(x) 表示背包中物品的总价值,x_i 表示第i 种物品的数量,V 表示背包的容量,c_i 表示第i 种物品的质量,v_i 表示第i 种物品的价值。
三、背包问题的求解方法背包问题的求解方法有很多,常见的有动态规划法、回溯法、贪心算法等。
这里我们以动态规划法为例进行介绍。
动态规划法的基本思想是将问题分解为子问题,通过求解子问题,最终得到原问题的解。
对于背包问题,我们可以将问题分解为:在容量为V 的情况下,如何选择物品使得总价值最大。
然后,我们可以通过递归的方式,依次求解子问题,最终得到原问题的解。
四、背包问题的应用实例背包问题是一个非常实用的优化问题,它在现实生活中有很多应用。
例如,一个果农需要根据市场需求和成本,选择合适的水果进行装箱;一个旅行者需要根据行李箱的容量和物品的价值,选择携带的物品等。
这些都可以通过背包问题来求解。
综上所述,背包问题是一个经典的优化问题,它有着广泛的应用。
背包问题解题⽅法总结最近在⽜客刷题遇到好⼏道背包问题,索性这两天集中⽕⼒刷了⼀些这类的题。
这⾥总结⼀下0-1背包、完全背包和多重背包三种基本的背包问题的解题套路。
(均基于动态规划的思想)0-1背包题⽬:有 N 件物品和容量为 W 的背包。
第 i 件物品的重量为 w_i,价值为 v_i,求将不超过背包容量的物品装⼊背包能得到的最⼤价值。
特点,每件物品的数量只有⼀个,可以选择放或不放某件物品。
⽤dp[i][j]表⽰将前 i+1 件总重量不超过 j 的物品放⼊背包能获得的最⼤价值,则可以⽤以下的转移⽅程来表⽰这个过程:\[dp[i,j] = max(dp[i - 1, j], dp[i-1, j-w[i]] + v[i]) \]注意到dp数组第i⾏的值更新只跟 i-1 ⾏有关,因此可以通过滚动数组或者反向更新的⽅式优化⼀下空间复杂度,在动态规划解题的时候这是⼀种常⽤的空间复杂度优化⽅式。
优化后的代码如下:for(int i = 0; i < N; i++){// 注意到这⾥dp需要从后往前更新,避免更新前就把旧值覆盖// 从实际意义上来说,因为每件物品只有⼀个,从后向前更新保证了更新是在还没放⼊过当前物品的前提下进⾏的for(int j = W; j >= w[i]; j--){dp[j] = Math.max(dp[j], dp[j - w[i]] + v[i]);}}完全背包题⽬:有 N 种物品和容量为 W 的背包。
第 i 种物品的重量为 w_i,价值为 v_i,每种物品的数量⽆限。
求将不超过背包容量的物品装⼊背包能得到的最⼤价值。
特点:每种物品的数量⽆限多。
考虑到每种物品的数量⽆限。
⽤dp[j]表⽰在重量不超过 j 的情况下背包中物品可以达到的最⼤价值,则转移⽅程如下:\[dp[j]=max(dp[j], dp[j-w[i]]+v[i]) \]核⼼代码如下:for(int i = 0; i < N; i++){for(int j = w[i]; j <= W; j++){ // 这⾥和0-1背包不同dp[j] = Math.max(dp[j], dp[j - w[i]] + v[i]);}}注意内层for循环是从前向后更新dp数组的,这是唯⼀和上⾯的0-1背包问题区别的地⽅。
(0-1)背包问题的解法小结1.动态规划法递推关系:– 考虑一个由前i 个物品(1≤i ≤n )定义的实例,物品的重量分别为w 1,…,w i ,价值分别为v 1,…,v i ,背包的承重量为j (1≤j ≤W )。
设V [I,j]为该实例的最优解的物品总价值– 分成两类子集:• 根据定义,在不包括第i 个物品的子集中,最优子集的价值是V [i -1,j ]• 在包括第i 个物品的子集中(因此,j -w ≥0),最优子集是由该物品和前i -1个物品中能够放进承重量为i -w j 的背包的最优子集组成。
这种最忧子集的总价值等于v i +V [i -1,j -w i ].0]0,[时,0 当0;][0,时,0初始条件:当],1[}],1[],,1[max{],[=≥=≥<≥⎩⎨⎧-+---=i V i j V j w j w j j i V v w j i V j i V j i V i i i i以记忆功能为基础的算法:用自顶向下的方式对给定的问题求解,另外维护一个类似自底向上动态规划算法使用的表格。
一开始的时候,用一种“null”符号创始化表中所有的单元,用来表明它们还没有被计算过。
然后,一旦需要计算一个新的值,该方法先检查表中相应的单元:如果该单元不是“null ”,它就简单地从表中取值;否则,就使用递归调用进行计算,然后把返回的结果记录在表中。
算法 MFKnapsack(I,j)//对背包问题实现记忆功能方法//输入:一个非负整数i 指出先考虑的物品数量,一个非负整数j 指出了背包的承重量 //输出:前i 个物品的最伏可行子集的价值//注意:我们把输入数组Weights[1..n],Values[1..n]和表格V[0..n,0..W]作为全局变量,除了行0和列0用0初始化以外,V 的所有单元都用-1做初始化。
if V[I,j]<01if j<Weights[i]value ←MFKnapsack(i-1,j)elsevalue ←max(MFKnapsack(i-1),j), Value[i]+MFKnapsack(i-1,j-eights[i]))V[I,j]←valuereturn V[I,j]2.贪心算法1) 背包问题基本步骤:首先计算每种物品单位重量的价值Vi/Wi ,然后,依贪心选择策略,将尽可能多的单位重量价值最高的物品装入背包。
P01: 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]}这个方程非常重要,基本上所有跟背包相关的问题的方程都是由它衍生出来的。
所以有必要将它详细解释一下:“将前i件物品放入容量为v的背包中”这个子问题,若只考虑第i件物品的策略(放或不放),那么就可以转化为一个只牵扯前i-1件物品的问题。
如果不放第i件物品,那么问题就转化为“前i-1件物品放入容量为v的背包中”,价值为f[i-1][v];如果放第i件物品,那么问题就转化为“前i-1件物品放入剩下的容量为v-c[i]的背包中”,此时能获得的最大价值就是f[i-1][v-c[i]]再加上通过放入第i件物品获得的价值w[i]。
优化空间复杂度以上方法的时间和空间复杂度均为O(VN),其中时间复杂度应该已经不能再优化了,但空间复杂度却可以优化到O。
先考虑上面讲的基本思路如何实现,肯定是有一个主循环i=1..N,每次算出来二维数组f[i][0..V]的所有值。
那么,如果只用一个数组f[0..V],能不能保证第i次循环结束后f[v]中表示的就是我们定义的状态f[i][v]呢?f[i][v]是由f[i-1][v]和f[i-1][v-c[i]]两个子问题递推而来,能否保证在推f[i][v]时(也即在第i次主循环中推f[v]时)能够得到f[i-1][v]和f[i-1][v-c[i]]的值呢?事实上,这要求在每次主循环中我们以v=V..0的顺序推f[v],这样才能保证推f[v]时f[v-c[i]]保存的是状态f[i-1][v-c[i]]的值。
背包问题系列算法详解背包问题是一个关于最优解的经典问题。
通常被讨论的最多的,最经典的背包问题是0-1背包问题(0-1 Knapsack Problem)。
它是一切背包问题及相关背包问题的基础。
本篇博文将详细分析0-1背包问题,并给出0-1背包问题的几种解法,同时也对0-1背包问题的内涵进行延伸,丰富其外延至完全背包问题和多重背包问题,并给出背包问题的算法实现过程,希望对大家有帮助。
一、0-1背包问题有N件物品和一个容量为V的背包。
第i件物品(每个物品只有一件)的费用是c[i],价值是w[i]。
求解将哪些物品装入背包可使价值总和最大。
(1)递归求解算法如下:#include "iostream"#define CAPACITY 10#define GOODSNUM 6using namespace std;int nVol[GOODSNUM];int nValue[GOODSNUM];int knapsack(int itemIndex,int vol);void main(){int i=0,j=0;while(i<GOODSNUM){cout<<"input the "<<i+1<<"th item(volume and value):";cin>>nVol[i]>>nValue[i];i++;}cout<<"The max value is: "<<knapsack(GOODSNUM,CAPACITY)<<endl;}int knapsack(int itemIndex,int vol){if (itemIndex==0||vol==0){return 0;}else if (vol>=nVol[itemIndex] &&knapsack(itemIndex-1,vol)<knapsack(itemIndex-1,vol-nVol[itemIndex])+nValue[itemIndex ]){return knapsack(itemIndex-1,vol-nVol[itemIndex])+nValue[itemIndex];}elsereturn knapsack(itemIndex-1,vol);}分析:递归求解,求解过程中的绝大部分变量存在重复求解的过程,算法的效率较低,有待改进;那怎么改进呢?最有效的是用数组保存每次计算的结果,不用重复计算,于是有二维数组求解。
使用穷举法解决0—1背包问题问题描述:有不同价值、不同重量的物品n件,求从这n件物品中选取一部分物品的选择方案,使选中物品的总重量不超过指定的限制重量,但选中物品的价值之和最大。
设n个物品的重量和价值分别存储于数组w[ ]和v[ ]中,限制重量为tw.考虑一个n元组(x0,x1,…,xn-1),其中xi=0 表示第i个物品没有选取,而xi=1则表示第i个物品被选取。
用枚举法解决背包问题,需要枚举所有的选取方案,而根据上述方法,我们只要枚举所有的n元组,就可以得到问题的解。
显然,每个分量取值为0或1的n元组的个数共为2n个。
而每个n元组其实对应了一个长度为n的二进制数,且这些二进制数的取值范围为0~2n-1.因此,如果把0~2n-1分别转化为相应的二进制数,则可以得到我们所需要的2n 个n元组。
下面是我据此思路编的一个小程序。
程序在VC6.0,win xp下编译运行成功。
程序测试结果,截图如下:背包问题的递归算法#include//物品总种数不是常量,没法根据它来决定数组的长度,只有先定义个长度了#define N 100int n ;//物品总种数double limitW ;//限制的总重量double totV ;//全部物品的总价值double maxv ;//解的总价值int option[N];//解的选择int cop[N];//当前解的选择struct{//物品结构double weight ;double value ;}a[N];//参数为物品i,当前选择已经达到的重量和tw,本方案可能达到的总价值void find(int i,doubletw,double tv){int k ;//物品i包含在当前方案的可能性if(tw+a.weight<=limitW){cop=1 ;if(i{find(i+1,tw+a.weight,tv);}else{for(k=0;koption[k]=cop[k];maxv=tv ;}}cop=0 ;//物品i不包含在当前方案的可能性if(tv-a.value>maxv){if(i{find(i+1,tw,tv-a.value);}else{for(k=0;koption[k]=cop[k];maxv=tv-a.value ;}}}void main(){int k ;double w,v ;printf("输入物品种数:");scanf("%d",&n);printf("输入各物品的重量和价值:");for(totV=0.0,k=0;k{scanf("%lf%lf",&w,&v);a[k].weight=w ;a[k].value=v ;totV+=v ;}printf("输入限制重量:");scanf("%lf",&limitW);maxv=0.0 ;for(k=0;kcop[k]=0 ;find(0,0.0,totV);for(k=0;kif(option[k])printf("%4d",k+1);printf("总价值为: %2f",maxv);}0/1背包问题的递归算法(2006-4-21 19:52:00)/*#include <stdio.h>#define N 100 //物品总种数不是常量,没法根据它来决定数组的长度,只有先定义个长度了int n;//物品总种数double limitW;//限制的总重量double totV;//全部物品的总价值double maxv;//解的总价值int option[N];//解的选择int cop[N];//当前解的选择struct {//物品结构double weight;double value;}a[N];//参数为物品i,当前选择已经达到的重量和tw,本方案可能达到的总价值void find(int i,double tw,double tv){int k;//物品i包含在当前方案的可能性if(tw+a[i].weight <= limitW){cop[i]=1;if(i<n-1)find(i+1,tw+a[i].weight,tv);else{for(k=0;k<n;++k)option[k]=cop[k];maxv=tv;}}cop[i]=0;//物品i不包含在当前方案的可能性if(tv-a[i].value>maxv){if(i<n-1)find(i+1,tw,tv-a[i].value); else{for(k=0;k<n;++k)option[k]=cop[k];maxv=tv-a[i].value;}}}void main(){int k;double w,v;printf("输入物品种数:");scanf("%d",&n);printf("输入各物品的重量和价值:"); for(totV=0.0,k=0;k<n;++k){scanf("%lf %lf",&w,&v);a[k].weight = w;a[k].value = v;totV += v;}printf("输入限制重量:");scanf("%lf",&limitW);maxv=0.0;for(k=0;k<n;++k)cop[k]=0;find(0,0.0,totV);for(k=0;k<n;++k)if(option[k])printf("%4d",k+1); printf("总价值为: %2f",maxv);}0/1背包问题 c++实现动态规划算法2008-11-23 23:28#include <iostream>#include <iomanip>using namespace std;const int C=10;const int N=5;template <class T>T max(const T a,const T b){return a>b?a:b;}/*01背包问题m为记录数组 m[i][j]代表在有j容量的条件下,从i开始往后的物品中可以取得的最大价值w为质量数组,v为价值数组n为物品个数,c为开始容量*/void knapsack(int **m,const int n,const int c,const int *w,const int *v) {/*m[n][j]首先计算m[n][j]的意思是容量为j ,放第n个物品可以取得的最大价值,当然当j比此物品的重量小时,装不下,m[n][j]为0当j比此物品重量小时,能取得的最大价值就是v[n]*/for(int i=0;i<w[n]&&i<=c;i++)m[n][i]=0;for(i=w[n];i<=c;i++)m[n][i]=v[n];/*计算完m[n][1,2,3……]后就可以用递推公式*/for(i=n-1;i>1;i--){for(int j=0;j<w[i]&&j<=c;j++)m[i][j]=m[i+1][j];for(j=w[i];j<=c;j++)m[i][j]=max(m[i+1][j],m[i+1][j-w[i]]+v[i]);}m[1][c]=max(m[2][c],m[2][c-w[1]]+v[1]);}void traceback(int **m,int n,int c,int *x,int *w) {for(int i=1;i<n;i++){if(m[i][c]==m[i+1][c])x[i]=0;else{x[i]=1;c-=w[i];}}x[n]=(m[n][c]==0)?0:1;}int main(){int *v=new int[N+1];int *w=new int[N+1];int **m=new int*[N+1];int *x=new int [N+1];for(int i=0;i<N+1;i++){m[i]=new int[C+1];}cout<<"输入质量序列,"<<N<<"个"<<endl;for(i=1;i<=N;i++)cin>>w[i];cout<<"输入价值序列,"<<N<<"个"<<endl;for(i=1;i<=N;i++)cin>>v[i];knapsack(m,N,C,w,v);traceback(m,N,C,x,w);cout<<m[1][C]<<endl;for(i=1;i<=N;i++)cout<<x[i];for(i=0;i<N+1;i++){delete [C+1]m[i];}delete [N+1] m;return 1;}背包算法2009-04-16 21:07/*** 背包问题* 背包问题是计算机科学里的经典问题。
在最简单的形式中,包括试图将不同重量的数据项放到* 背包中.以使背包最后达到指定的总重量。
不需要把所有的选项都放入背包中。
* 举例来说,假设想要背包精确地承重20磅,并且有5个可以选择放入的数据项,它们的重量* 依次为11磅、8磅、7磅、6磅和5磅。
对于选择放入的数据项数量不大时,人类很善于通过观察* 就可以解决这个问题。
于是大概可以计算出只有8磅、7磅和5磅的数据项加在一起和为20磅。
* 如果想要计算机来解决这个问题,就需要给计算机更详细的指令。
算法如下:* 1.如果在这个过程中的任何时刻,选择的数据项的总和符合目标重量,工作就完成了。
* 2.从选择第一个数据项开始。
剩余的数据项的加和必须符合背包的目标重量减去第一个数据* 项的重量;这是一个新的目标重量。
* 3.逐个地试每种剩余数据顶组合的可能性。
但是,注意并不需要去试所有的组合,因为只要* 数据顶朗和大于目标重量的时候,就停止添加数据项。
* 4.如果设有组合合适的话,放弃第—‘个数据项,并且从第二个数据项开始再重复一边整个* 过程。