w+=a[i].w;;/a[i].w;
}else{
】
node->b=p;
}
}
}
ign=i;;;ign]=1;
}else{
X[a[i].sign]=0;
}
}
deletexnode;
'
deleteheap;
returnv;,&a[i].p);
b[i]=a[i];
}
intsum4=KnapSack4(n,a,C,X);4运行结果
分支限界法求解0/1背包问题的时间复杂度为:
遗传算法(Geneticalgorithm)
}
遗传算法是模拟达尔文的生物自然选择学说和自然界的生物进化过程的一种自适应全局概率搜索算法[2]。
它是由美国的教授1975年首先提出,其主要特点是直接对结构对象进行操作,不存在求导和函数连续性的限定;具有内在的隐并行性和良好的全局寻优能力;采用概率化的寻优方法,能自动获取和指导优化的搜索空间,自适应地调整搜索方向,不需要确定规则。
遗传算法是从代表问题可能潜在的解集的一个种群开始的,而一个种群则由经过基因编码的一定数目的个体组成。
因此,在一开始需要实现从表现型到基因型的映射即编码工作。
由于仿照基因编码的工作很复杂,我们往往进行简化,如二进制编码,初代种群产生之后,按照适者生存和优胜劣汰的原理,逐代演化产生出越来越好的近似解,在每一代,根据问题域中个体的适应度大小选择个体,并借助于自然遗传学的遗传算子)进行组合交叉和变异,产生出代表新的解集的种群。
这个过程将导致种群像自然进化一样的后生代种群比前代更加适应于环境,末代种群中的最优个体经过解码,可以作为问题近似最优解。
算法设计
遗传算法解决0-1背包问题的基本步骤如下:
(1)群体的初始化:
确定种群规模M,交叉概率pc、变异概率pm、染色体长度N即最大进化代数T。
随机初始化染色体,给出物体体积、物品价值v和背包容量c。
(2)产生遗传编码:
采用二进制n维矢量解X作为解空间参数的遗传编码,串的长度等于n,
=1表示该物体装入背包,
=0表示该物品没有被装入背包。
(3)适应度函数的构造:
适应度函数的建立是解决背包问题的关键。
首先背包问题的目标函数和约束条件文章前面已提出
数学模型:
约束条件:
,
|
现给出构造它的2种适应度函数:
(4)选择操作:
根据选择概率选择染色体,将上述的个体作为第一代,采用以正比于适应度的赌轮随机选择方式,每个个体适应度值为
,则i被选中的概率
;对于初始化后的种群,先计算出每条染色体的适应度值,再计算出其被选择的概率,将它们进行比较,把选择概率最小的一条染色体淘汰掉,并选择概率最大的一条染色体进行复制,用这条复制的染色体代替淘汰的染色体的位置。
(5)交叉操作:
判断染色体是否为活的染色体,若为活的染色体,则将染色体进行交叉,一般采用一点交叉方式,交叉概率为Pc,具体操作是在个体串中随机设定一个交叉点,实行交叉时,该点前后的两个个体的部分结构进行互换,并生成两个新的个体。
(6)变异操作:
染色体变异采用位点变异的方式。
位点变异比较简单,对于0-1背包问题来说,就是把染色体的变异位1变为0,0变为1,其他位保持不变。
变异概率为Pm,变异的目的是使其变异后的适应度大于或等于其原适应度。
先选择一个变异位进行变异,再计算它的适应度,看它是否大于或等于其原来的适应度,若不是的话就重新选择变异位进行变异操作。
对种群依次进行选择、交叉、变异后就检验得到的新个体,当某代得到的结果满足要求或当前代数等于结束代数时算法结束得到结果,否则重新选择、交叉、变异操作,直到得到满意的结果为止。
使用幂函数适应度函数的遗传算法全局搜索效率比较高[2]。
3算法分析与比较
通过上面几种算法基本原理的介绍和分析,得到了不同方法解决NP难的0-1背包问题。
下面从时间、空间复杂度、准确性等方面进行进一步的分析比较。
#
动态规划算法的空间和时间复杂度由物品的数量和背包的承重量来决定。
若物品数量为n,背包承重量为c,初始化数组需要空间为O(nc),两重for循环时间复杂度为O(nc)。
动态规划能够保证求解的正确性,但它速度慢,空间消耗大。
贪心算法的时间复杂度为O(nlogn)。
但贪心算法属于近似算法,速度快,时间消耗少,但不能确定结果为最优解,体现了该算法的局限性。
遗传算法跟贪心算法一样,也是一种近似算法。
它的时间复杂度取决于采用的适应度函数。
第一种适应度函数对遗传算法的参数比较敏感,幂函数的适应度函数的遗传函数能获得高质量的解。
算法的效率分析
(1)蛮力法
对于一个有n个元素的集合,其子集数量为2^n,所以,不论生成子集的算法效率有多高,蛮力法都会导致一个2^n的算法
(2)贪心法
贪心算法总是作出在当前看来是最好的选择,即贪心算法并不从整体最优解上加以考虑,它所作出的选择只是在某种意义上的局部最优解。
贪心算法不是对所有问题都能得到整体最优解,但对范围相当广的许多问题它能产生整体最优解。
在一些情况下,即使贪心算法不能得到整体最优解,但其最终结果却是最优解的很好近似解。
贪心算法的时间复杂度为O(nlogn)。
(3)动态规划法
从m(i,j)的递归式容易看出,算法Knaspack需要O(nc)计算时间;Traceback需O(n)计算时间;算法总体需要O(nc)计算时间。
%
(4)回溯法
由于计算上界函数需要O(n)时间,在最坏情况下有个右孩子结点需要上界函数,故计算0-1背包问题的回溯算法所需的计算时间复杂度为。
对回溯法的改进主要是对判断是否移动右子树上,一种更有效的方法是按效益密度vi/wi对剩余对象排序,将对象按密度递减的顺序去填充背包的剩余容量,当遇到第一个不能全部放人背包的对象时,就使用它的一部分。
回溯算法的运行时间取决于它在搜索过程中所生成的结点数,而限界函数可以大量减少所生成的结点个数,省去许多无谓的搜索,使得搜索速度更快,其调用限界函数计算上界需花费O(n)时间,最坏情况下有个结点需调用限界函数,需花费O(n)时间,所以该算法的时间复杂度为。
(5)分枝-限界法
分支限界法求解0/1背包问题的时间复杂度为:
为了直观表示,特将四种算法的时间复杂度总结如下:
(1)为了更好地说明问题,现在对不同问题规模三种不同算法所需要的时间进行比较。
随着问题规模的增大,各算法的计算时间都在增大,由于回溯法相对于其他算法所增加的时间更加显著,特此,单独考虑回溯法的情况。
(2)此种情况下背包的容量为100,不同问题规模回溯法所用时间所下表所示
5由以上测试时间可以很好的验证,当背包容量和问题规模达到一定程度时,用回溯法解决背包问题,因此随着物件数n的增大,其解的空间将以
级增长,当n大到一定程度上,用此算法解决背包问题将是不现实的。
这正好与理论分析的情况是一致的。
6从实验中也可以发现,当问题规模很小的时候,四种算法都有较好的稳定性,计算时间都相差不多。
随着问题规模的增大,各算法的计算时间差别逐渐显现出来。
7对比以上四种算法可以看出,各种算法都有自己的特点,贪心算法速度比较快,但是所得的解有时可能只是局部最优解;分枝限界法需要
的解空间。
故该算法不常用在背包问题求解;回溯法比分枝限界在占用内存方面具有优势。
回溯法占用的内存是0(解空间的最大路径长度),而分枝限界所占用的内存为0(解空间大小)。
对于一个子集空间,回溯法需要0(n)的内存空间,而分枝限界则需要
的空间。
虽然最大收益或最小耗费分枝限界在直觉上要好于回溯法,并且在许多情况下可能会比回溯法检查更少的结点,但在实际应用中,它可能会在回溯法超出允许的时间限制之前就超出了内存的限制。
解决背包问题算法比较结果
4结论
目前,0-1背包问题还没有找到完美的求解最优解的方法,现在的智能算法都只能在一定的范围求解,各种算法都有一定的局限性[6]。
对于0-1背包问题的探索,一方面要在现有的算法如动态规划算法,贪心算法等算法上改进和完善,还要在其他学科的算法中获得启示,如从生物中得到启示的遗传算法,研究出解决0-1背包的新算法。
0-1背包问题是最基本的背包问题,它包含了背包问题中设计状态、方程的最基本思想,另外,别的类型的背包问题往往也可以转换成0-1背包问题求解。
故一定要仔细体会上面基本思路的得出方法,状态转移方程的意义,以及最后怎样优化的空间复杂度。
从计算复杂性理论看,背包问题是NP完全问题。
半个多世纪以来,该问题一直是算法与复杂性研究的热门话题。
通过对0-1背包问题的算法研究可以看出,回溯法和分枝限界法等可以得到问题的最优解,可是计算时间太慢;动态规划法也可以得到最优解,当m>2^n时,算法需要n2^n的计算时间,这与回溯法存在一样的缺点——计算速度慢;采用贪心算法,虽然耗费上优于前者,但是不一定是最优解。
目前,以上几种方法中回溯法、动态规划法、贪心法都广泛地应用到不同的实际问题中,并在应用中不断地改进。
5参考文献:
[1]王晓东.计算计算法设计与分析[M].北京:
电子工业出版社,2003
[2]程春英,张玉春.利用遗传算法求解0/1背包问题[A].内蒙古民族大学学报(自然科学版)第25卷,第6期,2010
[3]吕聪颖,赵刚彬,周春光.求解0—1背包问题的动态规划法分析[A].南阳理工学院学报第3卷第2期,2011
[4]曹亚非.背包问题中贪心算法的应用探讨[A].ValleySilicon
[5]曹珊珊.动态规划算法在0/1背包问题中的应用与分析[A].信息产业
[6]李雯瑞.0—1背包问题的求解算法设计与分析[A].软件导刊第11卷第6期,2012