算法分析与程序设计动态规划及回溯法解01背包问题.doc

上传人:豆**** 文档编号:28496464 上传时间:2022-07-28 格式:DOC 页数:40 大小:263KB
返回 下载 相关 举报
算法分析与程序设计动态规划及回溯法解01背包问题.doc_第1页
第1页 / 共40页
算法分析与程序设计动态规划及回溯法解01背包问题.doc_第2页
第2页 / 共40页
点击查看更多>>
资源描述

《算法分析与程序设计动态规划及回溯法解01背包问题.doc》由会员分享,可在线阅读,更多相关《算法分析与程序设计动态规划及回溯法解01背包问题.doc(40页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。

1、Four short words sum up what has lifted most successful individuals above the crowd: a little bit more.-author-date算法分析与程序设计动态规划及回溯法解01背包问题学年论文实施细则及格式动态规划法、回溯法解0-1背包问题2012级 计科 庞佳奇一、 问题描述与分析1. 动态规划算法通常用于求解具有某种最优性质的问题。在这类问题中,可能会有许多可行解。每一个解都对应于一个值,我们希望找到具有最优值的解。动态规划算法与分治法类似,其基本思想也是将待求解问题分解成若干个子问题,先求解子问

2、题,然后从这些子问题的解得到原问题的解。与分治法不同的是,适合于用动态规划求解的问题,经分解得到子问题往往不是互相独立的。若用分治法来解这类问题,则分解得到的子问题数目太多,有些子问题被重复计算了很多次。如果我们能够保存已解决的子问题的答案,而在需要时再找出已求得的答案,这样就可以避免大量的重复计算,节省时间。我们可以用一个表来记录所有已解的子问题的答案。不管该子问题以后是否被用到,只要它被计算过,就将其结果填入表中。这就是动态规划法的基本思路。具体的动态规划算法多种多样,但它们具有相同的填表格式。多阶段决策问题中,各个阶段采取的决策,一般来说是与时间有关的,决策依赖于当前状态,又随即引起状态

3、的转移,一个决策序列就是在变化的状态中产生出来的,故有“动态”的含义,称这种解决多阶段决策最优化问题的方法为动态规划方法。任何思想方法都有一定的局限性,超出了特定条件,它就失去了作用。同样,动态规划也并不是万能的。适用动态规划的问题必须满足最优化原理和无后效性。1.最优化原理(最优子结构性质) 最优化原理可这样阐述:一个最优化策略具有这样的性质,不论过去状态和决策如何,对前面的决策所形成的状态而言,余下的诸决策必须构成最优策略。简而言之,一个最优化策略的子策略总是最优的。一个问题满足最优化原理又称其具有最优子结构性质。2.无后效性将各阶段按照一定的次序排列好之后,对于某个给定的阶段状态,它以前

4、各阶段的状态无法直接影响它未来的决策,而只能通过当前的这个状态。换句话说,每个状态都是过去历史的一个完整总结。这就是无后向性,又称为无后效性。3.子问题的重叠性 动态规划将原来具有指数级时间复杂度的搜索算法改进成了具有多项式时间复杂度的算法。其中的关键在于解决冗余,这是动态规划算法的根本目的。动态规划实质上是一种以空间换时间的技术,它在实现的过程中,不得不存储产生过程中的各种状态,所以它的空间复杂度要大于其它的算法。01背包是在M件物品取出若干件放在空间为W的背包里,每件物品的体积为W1,W2Wn,与之相对应的价值为P1,P2Pn。求出获得最大价值的方案。2. 回溯法(探索与回溯法)是一种选优

5、搜索法,按选优条件向前搜索,以达到目标。但当探索到某一步时,发现原先选择并不优或达不到目标,就退回一步重新选择,这种走不通就退回再走的技术为回溯法,而满足回溯条件的某个状态的点称为“回溯点”。在包含问题的所有解的解空间树中,按照深度优先搜索的策略,从根结点出发深度探索解空间树。当探索到某一结点时,要先判断该结点是否包含问题的解,如果包含,就从该结点出发继续探索下去,如果该结点不包含问题的解,则逐层向其祖先结点回溯。(其实回溯法就是对隐式图的深度优先搜索算法)。 若用回溯法求问题的所有解时,要回溯到根,且根结点的所有可行的子树都要已被搜索遍才结束。 而若使用回溯法求任一个解时,只要搜索到问题的一

6、个解就可以结束可用回溯法求解的问题P,通常要能表达为:对于已知的由n元组(x1,x2,xn)组成的一个状态空间E=(x1,x2,xn)xiSi ,i=1,2,n,给定关于n元组中的一个分量的一个约束集D,要求E中满足D的全部约束条件的所有n元组。其中Si是分量xi的定义域,且 |Si| 有限,i=1,2,n。我们称E中满足D的全部约束条件的任一n元组为问题P的一个解。解问题P的最朴素的方法就是枚举法,即对E中的所有n元组逐一地检测其是否满足D的全部约束,若满足,则为问题P的一个解。但显然,其计算量是相当大的。我们发现,对于许多问题,所给定的约束集D具有完备性,即i元组(x1,x2,xi)满足D

7、中仅涉及到x1,x2,xi的所有约束意味着j(j=i)元组(x1,x2,xj)一定也满足D中仅涉及到x1,x2,xj的所有约束,i=1,2,n。换句话说,只要存在0jn-1,使得(x1,x2,xj)违反D中仅涉及到x1,x2,xj的约束之一,则以(x1,x2,xj)为前缀的任何n元组(x1,x2,xj,xj+1,xn)一定也违反D中仅涉及到x1,x2,xi的一个约束,nij。因此,对于约束集D具有完备性的问题P,一旦检测断定某个j元组(x1,x2,xj)违反D中仅涉及x1,x2,xj的一个约束,就可以肯定,以(x1,x2,xj)为前缀的任何n元组(x1,x2,xj,xj+1,xn)都不会是问题

8、P的解,因而就不必去搜索它们、检测它们。回溯法正是针对这类问题,利用这类问题的上述性质而提出来的比枚举法效率更高的算法。二、 算法设计(或算法步骤)1. 这是最基础的背包问题,特点是:每种物品仅有一件,可以选择放或不放。用子问题定义状态:即fiv表示前i件物品恰放入一个容量为v的背包可以获得的最大价值。则其状态转移方程便是: fiv=maxfi-1v,fi-1v-ci+wi 这个方程非常重要,基本上所有跟背包相关的问题的方程都是由它衍生出来的。所以有必要将它详细解释一下:“将前i件物品放入容量为v的背包中”这个子问题,若只考虑第i件物品的策略(放或不放),那么就可以转化为一个只牵扯前i-1件物

9、品的问题。如果不放第i件物品,那么问题就转化为“前i-1件物品放入容量为v的背包中”,价值为fi-1v;如果放第i件物品,那么问题就转化为“前i-1件物品放入剩下的容量为v-ci的背包中”,此时能获得的最大价值就是fi-1v-ci再加上通过放入第i件物品获得的价值wi。2. (1)分析要解决的问题,给出你的思路,可以借助图表等辅助表达。01背包问题用回溯法实现就是要枚举其所有的解空间,时间复杂度为(2)nO左右。搜索的具体方法如下:对于每一个物品i,对于该物品只有选与不选2个决策,总共有n个物品,可以顺序依次考虑每个物品,这样就形成了一棵解空间树:基本思想就是遍历这棵树,以枚举所有情况,最后进

10、行判断,如果重量不超过背包容量,且价值最大的话,该方案就是最后的答案。利用回溯算法写还可以加入一些优化,进行剪枝,因为很多情况是没有意义的,例如当重量大于背包容量的时候,没有必要对剩下的物品再来决策了。或者将剩下的所有物品都选取其总价值也没有目前已经求得的方案的价值还大的话,也是可以剪枝的。(2)分析利用你的想法解决该问题可能会有怎样的时空复杂度。时间复杂度估计:(2)nO因为物品只有选与不选2个决策,而总共有n个物品,所以时间复杂度为(2)nO。空间复杂度估计:()On因为递归栈最多达到n层,而且存储所有物品的信息也只需要常数个一维数组,所以最终的空间复杂度为()On。三、 算法实现1. 动

11、态规划#include#includeint c5050; int w10,v10; int x10; int n; void KNAPSACK_DP(int n,int W);void OUTPUT_SACK(int c5050,int k) ;void KNAPSACK_DP(int n,int W) int i,k;for(k=0;k=W;k+) c0k=0; for(i=1;i=n;i+) ci0=0; for(k=1;k=W;k+) if(wici-1k) cik=vi+ci-1k-wi; else cik=ci-1k; else cik=ci-1k; void OUTPUT_SAC

12、K(int c5050,int k) int i;for(i=n;i=2;i-) if(cik=ci-1k) xi=0; else xi=1; k=k-wi; x1=(c1k?1:0); for(i=1;i=n;i+) printf(%4d,xi); void main() int m; int i,j,k;printf(输入物品个数:);scanf(%d,&n);printf(依次输入物品的重量:n);for(i=1;i=n;i+) scanf(%d,&wi);printf(依次输入物品的价值:n);for(i=1;i=n;i+) scanf(%d,&vi);printf(输入背包最大容量:

13、n);scanf(%d,&m); for(i=1;i=m;i+) printf(%4d,i); printf(n); KNAPSACK_DP(n,m); printf(构造最优解过程如下:n);for(j=1;j=5;j+) for(k=1;k=m;k+) printf(%4d,cjk); printf(n); printf(最优解为:n);OUTPUT_SACK(c,m); system(pause);2. 回溯法#include #include #include typedef struct goods double *value; /价值 double *weight; /重量 cha

14、r *select; /是否选中到方案 int num;/物品数量 double limitw; /限制重量GOODS;double maxvalue,totalvalue; char *select1; void backpack(GOODS *g, int i, double tw, double tv) int k; if (tw + g-weighti limitw) select1i = 1; if (i num - 1) backpack(g, i + 1, tw + g-weighti, tv); else for (k = 0; k num; +k) g-selectk = s

15、elect1k;maxvalue = tv; select1i = 0; if (tv - g-valuei maxvalue) if (i num - 1) backpack(g, i + 1, tw, tv - g-valuei); else for (k = 0; k num; +k) g-selectk = select1k;maxvalue = tv - g-valuei; int main() double sumweight; GOODS g; int i; printf(背包最大重量:); scanf(%lf,&g.limitw); printf(可选物品数量:); scanf

16、(%d,&g.num); if(!(g.value = (double *)malloc(sizeof(double)*g.num) printf(内存分配失败n); exit(0); if(!(g.weight = (double *)malloc(sizeof(double)*g.num) printf(内存分配失败n); exit(0); if(!(g.select = (char *)malloc(sizeof(char)*g.num) printf(内存分配失败n); exit(0); if(!(select1 = (char *)malloc(sizeof(char)*g.num)

17、 printf(内存分配失败n); exit(0); totalvalue=0; for (i = 0; i g.num; i+) printf(输入第%d号物品的重量和价值:,i + 1); scanf(%lf%lf,&g.weighti,&g.valuei); totalvalue+=g.valuei; printf(n背包最大能装的重量为:%.2fnn,g.limitw); for (i = 0; i g.num; i+) printf(第%d号物品重:%.2f,价值:%.2fn, i + 1, g.weighti, g.valuei); for (i = 0; i g.num; i+)

18、 select1i=0; maxvalue=0; backpack(&g,0,0.0,totalvalue); sumweight=0; printf(n可将以下物品装入背包,使背包装的物品价值最大:n); for (i = 0; i g.num; +i) if (g.selecti) printf(第%d号物品,重量:%.2f,价值:%.2fn, i + 1, g.weighti, g.valuei); sumweight+=g.weighti; printf(n总重量为: %.2f,总价值为:%.2fn, sumweight, maxvalue ); return 0;四、算法分析(与改进

19、)(1)算法实现的复杂度在问题规模很大时可以接受吗?答:不可以接受。因为该算法是指数级别的时间复杂度为(*2)nOn,当n较大时,也能在一定时间内无法得出结果。空间复杂度为()On,还可以接受。但是综合上面分析,时间复杂度成为极大地瓶颈。所以规模很大时不可以接受。 (2)所选用的数据结构合适吗?答:合适,只用到一维数组。使用的数据结构简单,易理解。能够对数组中的每个元素随机访问。(3)该算法都存在哪几类可能出现的情况,你的测试完全覆盖了你所想到的这些 情况吗,测试结果如何?答:测试全面。输入规模为0时,程序自动结束。输入总重量小于背包容量时,结果为所有物品的价值总和。输入的总重量大于背包容量时,结果为能装入所有方案中最大的值。(4)叙述通过实验你对回溯法方法的理解及其优缺点优点:回溯法在普通的深度优先搜索的基础上增加了限界函数,对不必要的解空间树进行剪枝,使得可行解的数量大大减少,增加了搜索速度。回溯法的设计也非常简单,即简单的枚举搜索策略,只需要分析细节过程就能增加剪枝的操作。另外,空间复杂度通常非常小,只有搜索深度左右的空间。缺点:回溯法虽然设计简单,但是时间复杂度非常高,通常是指数级别的。而且回溯法的难点在于限界函数的设计。而且回溯法通常需要遍历完所有的解空间才能得出最优值,而不是像宽度优先搜索一样第一次求出的值便是最优值。报 告 成 绩 单评语成绩-

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 教育专区 > 小学资料

本站为文档C TO C交易模式,本站只提供存储空间、用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。本站仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知淘文阁网,我们立即给予删除!客服QQ:136780468 微信:18945177775 电话:18904686070

工信部备案号:黑ICP备15003705号© 2020-2023 www.taowenge.com 淘文阁