- 1、本文档共41页,可阅读全部内容。
- 2、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。
- 3、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载。
- 4、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
查看更多
算法第2章_穷举与回溯
如 保证每行、每列只有1个。如一个一维数组 f【9】:开始设f[1]-----f[8]初值为0;然后分离这8个数字,如第一次分离出个位是1,则f[1]=f[1]+1;第二次分离出十位是5,则f[5]=f[5] +1;…,这样经过一篇分离,如数字不重复则f[1]-----f[8] 值为均1。 如果有一个不是,证明数字重复,不是要找的答案。 2.3 回溯法及其描述 2.3.1 回溯的基本概念 回溯法找出求解问题的线索往前试探,若试探成功,即得到解;若试探失败,就逐步往回退,换其他路线再往前试探。 回溯法可以形象地概括为“向前走,碰壁回头”。 与穷举法相比,回溯法的“聪明”之处在于能适时“回头”,若再往前走不可能得到解,就回溯,退一步另找线路,这样可省去大量的无效操作。 应用回溯设计求解实际问题,由于解空间的结构差异,而且很难计算与估计回溯产生的结点数,因此回溯计算复杂度是分析回溯法效率时遇到的主要困难。 回溯法产生的结点数通常不足解空间结点数的3%,这也是回溯法的计算效率大大高于穷举法的原因所在。 2.3.2 回溯法描述 1. 回溯的一般方法 2. 回溯算法框架描述 /* 输入正整数n,m,(n≥m) */ i=1;a[i]=元素初值; while (1) { g=1;for(k=i-1;k=1;k--) if( 约束条件1 ) g=0; /* 检测,不满足则返回 */ if(g 约束条件2) printf(a[1-m]); /* 输出一个解 */ if(in g) {i++;a[i]=取值点;continue;} while(a[i]==回溯点 i1) i--; /* 向前回溯 */ if(a[i]==n i==1) break; /* 退出循环,结束 */ else a[i]=a[i]+1; } 2.3.3 回溯法的效益分析 回溯法的时间通常取决于状态空间树上实际生成的那部分问题状态的数目。对于元组长度为n的问题,若其状态空间树中结点总数为n!,则回溯算法的最坏情形的时间复杂度可达O(p(n)n!); 对于某一具体实际问题的回溯求解,常通过计算实际生成结点数的方法即蒙特卡罗方法(Monte carlo)来评估其计算效率。 把所求得的随机路径上的结点数(或若干条随机路径的结点数的平均值)与状态空间树上的总结点数进行比较,由其比值可以初步看出回溯设计的效益。 2.4 回溯设计应用 2.4.1 桥本分数式 1. 问题提出 日本数学家桥本吉彦教授于1993年10月在我国山东举行的中日美三国数学教育研讨会上向与会者提出以下填数趣题: 把1,2,...,9这9个数字填入下式的九个方格中(数字不得重复),使下面的分数等式成立 □ □ □ ── + ── = ── □□ □□ □□ 桥本教授当即给出了一个解答。这一分数式填数趣题究竟共有多少个解答? 试求出所有解答。(等式左边两个分数交换次序只算一个解答)。 1. 回溯算法设计 设置a数组,式中每一□位置用一个数组元素来表示 . 为判断数字是否重复,设置中间变量g:若出现某两数字相同(即a(i)=a(k))或a(1)a(4),则赋值g=0(重复标记)。 首先从a(1)=1开始,逐步给a(i)(1≤i≤9)赋值,每一个a(i)赋值从1开始递增至9。直至a(9)赋值,判断: 若i=9,g=1,等式同时满足,则为一组解,用n统计解的个数后,格式打印输出这组解。 若i9 且g=1,表明还不到九个数字,则下一个a(i)从1开始赋值继续。 若a(9)=9 ,则返回前一个数组元素a(8)增1 赋值(此时,a(9)又从1开始)再试。若a(8)=9 ,则返回前一个数组元素a(7)增1 赋值再试。 依此类推,直到a(1)=9时,已无法返回,意味着已全部试毕,求解结束。 2.算法描述 输入正整数n,m,(n≥m); i=1;a[i]=元素初值; while (1) { g=1;for(k=i-1;k=1;k--) if( 约束条件1 ) g=0; /* 检测,不满足返回 */ if(g 约束条件2) printf(a[1-m]); /* 输出一个解 */ if(in g) {i++;a[i]=取值点;continue;} while(a[i]==回溯点 i1) i--; /* 回溯 */ if(a[i]==n i==1) break; /* 退出循环,结束 */ else a[i]=a[i]+1; } 2.算法描述 输入n=m=9; i=1; a[i
文档评论(0)