穷举法
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
第16章 穷举算法与实验
穷举方法是基于计算机特点而进行解题的思维方法。一般是在一时找不出解决问题的更好途径(即从数学上找不到求解的公式或规则)时,可以根据问题中的的部分条件(约束条件)将所有可能解的情况列举出来,然后通过一一验证是否符合整个问题的求解要求,而得到问题的解。这样解决问题的方法我们称之为穷举算法。穷举算法特点是算法简单,但运行时所花费的时间量大。因此,我们在用穷举方法解决问题时,应尽可能将明显的不符合条件的情况排除在外,以尽快取得问题的解。虽然穷举法效率并不高,但是适应一些没有明显规律可循的问题的解决。
因为穷举算法就是从所有可能的情况中搜索正确的答案,所以一般可按如下步骤: 第1步: 对于一种可能的情况,列举出来并计算其结果;
第2步:判断结果是否满足要求,如果不满足则执行第1步来搜索下一个可能的情况,如果满足要求,则表示寻找到一个正确的答案,执行下一步操作,如寻找其他正确(合适)的答案或者中断循环。
16.1三角形数问题
16.1.1 问题描述
将 ,F ,E ,D ,C ,B ,A 这六个变量排成如图所示的三角形,这六个变量分别取[1,6]上的
整数,且均不相同。求使三角形三条边上的变量之和相等的全部解。如图就是一个解。 A 6
B C 3 1
D F 2 4
E 5
16.1.2 问题分析
程序引入变量123456,,,,,i i i i i i ,代表,F ,E ,D ,C ,B ,A 并让它们分别顺序取1至6的正整数,在它们互不相同的前提条件下,测试由它们排成的如图所示的三角形三条边上的变量之和是否相等,如相等即为一种满足要求的排列,把它们输出。当这些变量取尽所有的组合后,程序就可得到全部可能的解。细节见下面的程序。 【程序1】
%穷举法解三角形数 for i1=1:6 for i2=1:6 if i1==i2 continue;
end
for i3=1:6
if i1==i3 || i2==i3
continue;
end
for i4=1:6
if i1==i4 || i2==i4 || i3==i4
continue;
end
for i5=1:6
if i1==i5 || i2==i5 || i3==i5 || i4==i5
continue;
end
for i6=1:6
if i1==i6 || i2==i6 || i3==i6 || i4==i6 || i5==i6
continue;
end
if i1+i2+i4==i1+i3+i6 && i1+i2+i4==i4+i5+i6
fprintf ('%6d\n',i1) ;
fprintf ('%4d%4d\n',i2,i3) ;
fprintf ('%2d%4d%4d\n\n',i4,i5,i6) ;
end
end
end
end
end
end
End
16.1.3 问题讨论
按穷举法编写的程序通常不能适应变化的情况。如问题改成有9 个变量排成三角形,每条边有4 个变量的情况,程序的循环重数就要相应改变,而且程序的复杂程度大大增加。
对一组数穷尽所有排列,还有更直接的方法。将一个排列看作一个长整数,则所有排列对应着一组整数。将这组整数按从小到大的顺序排列排成一个整数,从对应最小的整数开始。按数列的递增顺序逐一列举每个排列对应的每个整数,这能更有效地完成排列的穷举。从一个排列找出对应数列的下一个排列可在当前排列的基础上作部分调整来实现。倘若当前排列为1,2,4,6,5,3,并令其对应的长整数为124653。要寻找比长整数124653 更大的排列,可从该排列的最后一个数字顺序向前逐位考察,当发现排列中的某个数字比它前一个数字大时,如本例中的6 比它的前一位数字4 大,这说明还有对应更大整数的排列。但为了顺序从小到大列举出所有的排列,不能立即调整得太大,如本例中将数字6 与数字4 交换得到的排列126453 就不是排列124653 的下一个排列。为了得到排列124653 的下一个排列,应从已经考察过的那部分数字中选出比数字大,但又是它们中最小的那一个数字,比如数字5,与数字4 交换。该数字也是从后向前考察过程中第一个比4 大的数字。5 与4 交换后,得到排
列125643。在前面数字1,2,5 固定的情况下,还应选择对应最小整数的那个排列,为此 还需将后面那部分数字的排列顺序颠倒,如将数字6,4,3 的排列顺序颠倒,得到排列1, 2,5,3,4,6,这才是排列1,2,4,6,5,3 的下一个排列。
按以上想法编写的程序如下。 【改进的程序1’】
%穷举法 解三角形的其他方法 a=1:6;%构建序列数组
while ~all(a==6:-1:1) %判断是否达到最大的数列,即654321
if a(1)+a(2)+a(4)==a(1)+a(3)+a(6) && a(1)+a(2)+a(4)==a(4)+a(5)+a(6) fprintf ('%6d\n',a(1)) ;
fprintf ('%4d%4d\n',a(2),a(3)) ;
fprintf ('%2d%4d%4d\n\n',a(4),a(5),a(6)) ; end
for i1=6:-1:2
if all(a(i1)-a(i1-1)>0) %如果遇到比较大得数则开始替换 zc=7;
for j1=i1:6 %寻找一个最小的但大于比较数的且在考察区域的值进行交换 if a(j1)>a(i1-1) && a(j1) a(j2)=a(i1-1); %替换 a(i1-1)=zc; %替换 a(i1:end)=sort(a(i1:end)); %重排序,交换后的考察区域按降序排列 break; end end end 从上述问题解决的方法中,最重要的因素就是确定某种方法来确定所有的候选解。下面 再用一个示例来加以说明。 16.2 背包问题 16.2.1问题描述 有不同价值、不同重量的物品n 件,求从这n 件物品中选取一部分物品的选 择方案,使选中物品的总重量不超过指定的限制重量,但选中物品的价值之和最大。 16.2.2 问题分析 设n 个物品的重量和价值分别存储于数组] w[和] v[中,限制重量为tw 。考虑一个n 元组()110,...,,-n x x x ,其中0 i x =表示第i 个物品没有选取,而1i x =则表示第i 个物品被选