当前位置:文档之家› 第5章 回溯法

第5章 回溯法

第5章
教学要求

回溯
了解回溯算法的概念与回溯设计要领 掌握应用回溯算法求解桥本分数式、素数环、 数码串珠以及情侣拍照等典型案例
本章重点

理解回溯法 “向前走,碰壁回头”的实现
5.1 回溯概述

1. 回溯的概念
(1) 回溯法(Back track method)有“通用解题法”之美 称,是一种比枚举“聪明”的效率更高的搜索技术。

4. 4皇后问题的回溯举例
如何在4×4的方格棋盘上放置4个皇后,使它们互不攻击:

4皇后问题回溯描述
i=1;a[i]=1; while


(1) { g=1;for(k=i-1;k>=1;k--) if(a[i]=a[k] || abs(a[i]-a[k])=i-k) g=0; // 检测约束条件,不满足则返回 if(g && i==4) printf(a[1:4]); // 输出一个解 if(i<4 && g) {i++;a[i]=1;continue;} while(a[i]==4 && i>1) i--; // 向前回溯 if(a[i]==4 && i==1) break; //退出循环结束探索 else a[i]=a[i]+1; }
(2) 回溯描述 对于一般含参量m,n的搜索问题,输入正整数n,m,(n≥m) i=1;a[i]=<元素初值>; while (1) {for(g=1,k=i-1;k>=1;k--) if( <约束条件1> ) g=0; // 检测约束条件,不满足则返回 if(g && <约束条件2>) printf(a[1:m]); // 输出解 if(i<n && g) {i++;a[i]=<取值点>;continue;} while(a[i]=<回溯点> && i>1) i--; // 向前回溯 if(a[i]==n && i==1) break; // 退出循环,结束 else a[i]=a[i]+1; }
(2) 回溯法是一种试探求解的方法:通过对问题的归纳分 析,找出求解问题的一个线索,沿着这一线索往前试 探,若试探成功,即得到解;若试探失败,就逐步往 回退,换其他路线再往前试探。 (3) 回溯法可以形象地概括为“向前走,碰壁回头”,若 再往前走不可能得到解,就回溯,退一步另找线路, 这样可省去大量的无效操作,提高搜索效率。

2. 回潮设计描述
i=1;a[1]=1;s=0; while


(1) {g=1;for(k=i-1;k>=1;k--) if(a[i]==a[k]) {g=0;break;} // 两数相同,标记g=0 if(i==9 && g==1 && a[1]<a[4]) { m1=a[2]*10+a[3];m2=a[5]*10+a[6];m3=a[8]*10+a[9]; if(a[1]*m2*m3+a[4]*m1*m3==a[7]*m1*m2) // 判断等式 {s++;printf(“(%2d) ”,s); } // 输出一个解 } if(i< 9 && g==1) {i++;a[i]=1;continue;} // 不到9个数继续 while(a[i]==9 && i>1) i--; // 往前回溯 if(a[i]==9 && i==1) break; else a[i]++; // 至第1个数为9结束 }
5.4 逐位整除数探索
5.4.1


高逐位整除数
案例提出:
n位高逐位整除数:从其高位开始,高1位能被1整除(显 然), 高2位能被2整除,„,整个n位数能被n整除。 例如10245就是一个5位高逐位整除数。 对于指定的正整数n,共有多少个不同的n位高逐位整除 数?存在n位高逐位整除数的n是否有最大值? 试探索指定的n位高逐位整除数,输出所有n位高逐位整 除数。
5.2 桥本分数式
案例提出:


日本数学家桥本吉彦教授于1993年10月在我国山东举行的中日美三 国数学教育研讨会上提出以下填数趣题:把1,2,„,9 9个数字填入下 这 式的9个方格中(数字不得重复),使下面分数等式成立:

□ □ □ ── + ── = ── □□ □□ □□
桥本教授当即给出了一个解答。这一填数趣题的解是否唯一?如果 不唯一究竟有多少个解?试求出所有解答 (等式左边两个分数交换次 序只算一个解答)。•
a(1) a(4) a (7 ) a(2)a(3) a(5)a(6) a(8)a(9)
1. 回溯设计要点

设置a数组,式中每一□位置用一个数组元素表示:

为避免解重复,设a(1)<a(4),记式中3个分母分别为 m1=a(2)a(3)=a(2)*10+a(3) m2=a(5)a(6)=a(5)*10+a(6) m3=a(8)a(9)=a(8)*10+a(9) 所求分数等式等价于整数等式 a(1)*m2*m3+a(4)*m1*m3=a(7)*m1*•2成立。 m
设置中间变量g:先赋值g=1;若出现某两数字相同(即 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,a(1)*m2*m3+a(4)*m1*m3=a(7)*m1*m2• 时满 同 足,为一组解,用n统计解的个数后,格式输出这组解。 若i<9且g=1,表明还不到9个数字,则下一个a(i)从1开 始赋值继续。 若a(9)=9,则返回前一个数组元素a(8)增1赋值(此时, a(9)又从1开始)再试。若a(8)=9,则返回前一个数组元素 a(7)增1赋值再试。依此类推,直到a(1)=9时,已无法返 回,意味着已全部试毕,求解结束。
1. 回溯设计要点 设置a,数组,存放求解的高逐位整除数的各位, a[1]存储最高位数字,a[2]存储次高位数字,„, a[n]存储n位数的个位数字。 在a数组中,数组元素a[1]从1开始取值,显然 能被1整除;a[2]从0开始取值,存放第2位数, 前2位即a[1]*10+a[2]能被2整除;„。 为了判别已取i位数能否被i整除,设置j循环: for(r=0,j=1;j<=i;j++) { r=r*10+a[j]; r=r%i; }
(2)
建立数学模型 为了确定和为s的n个整数取值及这些整数的分布,使沿 环的部分和能完全覆盖[1,s],建立以下数学模型: 设圆圈的周长为s,在圆圈上划n条刻度,用a数组作标 记。起点为a(0)=0,约定a(1)-a(0)为第1个数,a(2)-a(1) 为第2个数,„,一般地a(i)-a(i-1)为第i个数。因共n个 数,显然刻度a(n)=s且与起点a(0)重合。 因n个数中至少有一个数为1(否则不能覆盖1),不妨 设第1个数为1,即a(1)=1。 n个数的每一个数都可以与(约定顺时针方向)相连的1, 2,„,n-1个数组成部分和。为构造部分和方便,定义 a(n+1)与a(1)重合,即 a(n+1)=s+a(1);定义a(n+2)与 a(2)重合,即a(n+2)=s+a(2); „;最后有a(2n-1)与 a(n-1)重合,即a(2n-1)=s+a(n-1)。
(1)
部分和的数量 一般地,求解环上有n个整数,其和为s,沿环的部分 和为区间[1-s]上的所有整数。 首先探讨沿圆环6个整数组成部分和的个数。 部分和为1个整数,共6个;相应部分和为5个相连整数 组成,也为6个。 部分和为2个相连整数组成,共6个;相应部分和为4个 相连整数组成,也为6个。 部分和为3个相连整数组成,共6个; 部分和为所有6个相连整数组成,共1个。 因而部分和的个数为:6×5+1=31 共有31个部分和,如果s=31,要覆盖[1,31],意味着 31个部分和没有相同的。 若环上为n个整数,部分和为n(n-1)+1个。
5.3 直尺与串珠
5.3.2

数码串珠
案例提出:
在某佛寺遗址考古发掘中意外发现一串奇特的数码珠 串,珠串上共串缀有6颗宝珠,每一宝珠上都刻有一个神 秘的正整数: (1) 6颗宝珠上的整数互不相同。 (2) 这6个整数之和为31,沿珠串相连的若干颗(1— 6颗)珠上整数之和为1,2,„,31不间断,即可以覆盖 区间[1,31]中的所有整数。 请确定珠串上6颗宝珠的整数及其相串的顺序。
2. 回溯实现


回溯法的试探搜索,是一种组织得井井有条的、能避免一些不必 要搜索的枚举式搜索。回溯法在问题的解空间树中,从根结点出 发搜索解空间树,搜索至解空间树的任意一点,先判断该结点是 否包含问题的解;如果肯定不包含,则跳过对该结点为根的子树 的搜索,逐层向其父结点回溯;否则,进入该子树,继续搜索。 从解的角度理解,回溯法将问题的候选解按某种顺序进行枚举和 检验。当发现当前候选解不可能是解时,就选择下一个候选解。 在回溯法中,放弃当前候选解,寻找下一个候选解的过程称为回 溯。若当前候选解除了不满足问题规模要求外,满足所有其他要 求时,继续扩大当前候选解的规模,并继续试探。如果当前候选 解满足包括问题规模在内的所有要求时,该候选解就是问题的一 个解。
5. 回溯法的效益分析
回溯求解过程实质上是遍历一棵“状态树”的过程,只要所激活的状 态结点满足终结条件,应该把它输出或保存。由于在回溯法求解问题时, 一般要求输出问题的所有解,因此在得到并输出一个解后并不终止,还要 进行回溯,以便得到问题的其他解,直至回溯到状态树的根且根的所有子 结点均已被搜索过为止。 回溯法的时间取决于状态空间树上实际生成的那部分问题状态的数目。 对于元组长度为n的问题,若其状态空间树中结点总数为n!,则回溯算法的 最坏情形的时间复杂度可达O(p(n)n!);若其状态空间树中结点总数为2n, 则回溯算法的最坏情形时间复杂度可达O(p(n)2n),其中p(n)为n的多项式。 应用回溯设计求解实际问题,由于解空间的结构差异,很难精确计算 与估计回溯产生的结点数,这是分析回溯法效率时遇到的主要困难。回溯 法实际产生的结点数通常只有解空间所有结点数的一小部分,这也是回溯 法的探索效率大大高于枚举的原因所在。
相关主题