`
hdy007
  • 浏览: 30931 次
最近访客 更多访客>>
文章分类
社区版块
存档分类

常用算法设计方法之穷举搜索法

阅读更多

穷举搜索法是对可能是解的众多候选解按某种顺序进行逐一枚举和检验,并从众找出那些符合要求的候选解作为问题的解。<o:p></o:p>

【问题】   ABCDEF这六个变量排成如图所示的三角形,这六个变量分别取[16]上的整数,且均不相同。求使三角形三条边上的变量之和相等的全部解。如图就是一个解。<o:p></o:p>

程序引入变量abcdef,并让它们分别顺序取16的证书,在它们互不相同的条件下,测试由它们排成的如图所示的三角形三条边上的变量之和是否相等,如相等即为一种满足要求的排列,把它们输出。当这些变量取尽所有的组合后,程序就可得到全部可能的解。细节见下面的程序。<o:p></o:p>

【程序1<o:p></o:p>

# include <stdio.h><o:p></o:p>

void main()<o:p></o:p>

{   int a,b,c,d,e,f;<o:p></o:p>

for (a=1;a<=6;a++)<o:p></o:p>

for (b=1;b<=6;b++)     {<o:p></o:p>

if (b==a)     continue;<o:p></o:p>

for (c=1;c<=6;c++)     {<o:p></o:p>

if (c==a)||(c==b)   continue;<o:p></o:p>

for (d=1;d<=6;d++)     {<o:p></o:p>

if (d==a)||(d==b)||(d==c)   continue;<o:p></o:p>

for (e=1;e<=6;e++)     {<o:p></o:p>

if (e==a)||(e==b)||(e==c)||(e==d)   continue;<o:p></o:p>

f=21-(a+b+c+d+e);<o:p></o:p>

if ((a+b+c==c+d+e))&&(a+b+c==e+f+a))   {<o:p></o:p>

printf(“%6d,a);<o:p></o:p>

printf(“%4d%4d”,b,f);<o:p></o:p>

printf(“%2d%4d%4d”,c,d,e);<o:p></o:p>

scanf(“%*c”);<o:p></o:p>

}<o:p></o:p>

}<o:p></o:p>

}<o:p></o:p>

}<o:p></o:p>

}<o:p></o:p>

}<o:p></o:p>

按穷举法编写的程序通常不能适应变化的情况。如问题改成有9个变量排成三角形,每条边有4个变量的情况,程序的循环重数就要相应改变。<o:p></o:p>

对一组数穷尽所有排列,还有更直接的方法。将一个排列看作一个长整数,则所有排列对应着一组整数。将这组整数按从小到大的顺序排列排成一个整数,从对应最小的整数开始。按数列的递增顺序逐一列举每个排列对应的每个整数,这能更有效地完成排列的穷举。从一个排列找出对应数列的下一个排列可在当前排列的基础上作部分调整来实现。倘若当前排列为124653,并令其对应的长整数为124653。要寻找比长整数124653更大的排列,可从该排列的最后一个数字顺序向前逐位考察,当发现排列中的某个数字比它前一个数字大时,如本例中的6比它的前一位数字4大,这说明还有对应更大整数的排列。但为了顺序从小到大列举出所有的排列,不能立即调整得太大,如本例中将数字6与数字4交换得到的排列126453就不是排列124653的下一个排列。为了得到排列124653的下一个排列,应从已经考察过的那部分数字中选出比数字大,但又是它们中最小的那一个数字,比如数字5,与数字4交换。该数字也是从后向前考察过程中第一个比4大的数字。54交换后,得到排列125643。在前面数字125固定的情况下,还应选择对应最小整数的那个排列,为此还需将后面那部分数字的排列顺序颠倒,如将数字643的排列顺序颠倒,得到排列125346,这才是排列124653的下一个排列。按以上想法编写的程序如下。<o:p></o:p>

【程序2<o:p></o:p>

# include <stdio.h><o:p></o:p>

# define SIDE_N   3<o:p></o:p>

# define LENGTH   3<o:p></o:p>

# define VARIABLES   6<o:p></o:p>

int A,B,C,D,E,F;<o:p></o:p>

int *pt[]={&A,&B,&C,&D,&E,&F};<o:p></o:p>

int *side[SIDE_N][LENGTH]={&A,&B,&C,&C,&D,&E,&E,&F,&A};<o:p></o:p>

int side_total[SIDE_N];<o:p></o:p>

main{}<o:p></o:p>

{   int i,j,t,equal;<o:p></o:p>

for (j=0;j<VARIABLES;j++)<o:p></o:p>

*pt[j]=j+1;<o:p></o:p>

while(1)<o:p></o:p>

{   for (i=0;i<SIDE_N;i++)<o:p></o:p>

{   for (t=j=0;j<LENGTH;j++)<o:p></o:p>

t+=*side[j];<o:p></o:p>

side_total=t;<o:p></o:p>

}<o:p></o:p>

for (equal=1,i=0;equal&&i<SIDE_N-1;i++)<o:p></o:p>

if (side_total!=side_total[i+1]   equal=0;<o:p></o:p>

if (equal)<o:p></o:p>

{   for (i=1;i<VARIABLES;i++)<o:p></o:p>

printf(“%4d”,*pt);<o:p></o:p>

printf(“\n”);<o:p></o:p>

scanf(“%*c”);<o:p></o:p>

}<o:p></o:p>

for (j=VARIABLES-1;j>0;j--)<o:p></o:p>

if (*pt[j]>*pt[j-1])   break;<o:p></o:p>

if (j==0)   break;<o:p></o:p>

for (i=VARIABLES-1;i>=j;i--)<o:p></o:p>

if (*pt>*pt[i-1])   break;<o:p></o:p>

t=*pt[j-1];* pt[j-1] =* pt; *pt=t;<o:p></o:p>

for (i=VARIABLES-1;i>j;i--,j++)<o:p></o:p>

{   t=*pt[j]; *pt[j] =* pt; *pt=t;   }<o:p></o:p>

}<o:p></o:p>

}<o:p></o:p>

从上述问题解决的方法中,最重要的因素就是确定某种方法来确定所有的候选解。下面再用一个示例来加以说明。<o:p></o:p>

【问题】   背包问题<o:p></o:p>

问题描述:有不同价值、不同重量的物品n件,求从这n件物品中选取一部分物品的选择方案,使选中物品的总重量不超过指定的限制重量,但选中物品的价值之和最大。<o:p></o:p>

n个物品的重量和价值分别存储于数组w[ ]v[ ]中,限制重量为tw。考虑一个n元组(x0x1xn-1),其中xi=0 表示第i个物品没有选取,而xi=1则表示第i个物品被选取。显然这个n元组等价于一个选择方案。用枚举法解决背包问题,需要枚举所有的选取方案,而根据上述方法,我们只要枚举所有的n元组,就可以得到问题的解。<o:p></o:p>

显然,每个分量取值为01n元组的个数共为2n个。而每个n元组其实对应了一个长度为n的二进制数,且这些二进制数的取值范围为02n-1。因此,如果把02n-1分别转化为相应的二进制数,则可以得到我们所需要的2nn元组。<o:p></o:p>

【算法】<o:p></o:p>

maxv=0;<o:p></o:p>

for (i=0;i<2n;i++)<o:p></o:p>

{   B[0..n-1]=0;<o:p></o:p>

i转化为二进制数,存储于数组B;<o:p></o:p>

temp_w=0;<o:p></o:p>

temp_v=0;<o:p></o:p>

for (j=0;j<n;j++)<o:p></o:p>

{   if (B[j]==1)<o:p></o:p>

{   temp_w=temp_w+w[j];<o:p></o:p>

temp_v=temp_v+v[j];<o:p></o:p>

}<o:p></o:p>

if ((temp_w<=tw)&&(temp_v>maxv))<o:p></o:p>

{   maxv=temp_v;<o:p></o:p>

保存该B数组;<o:p></o:p>

}<o:p></o:p>

}<o:p></o:p>

}

分享到:
评论

相关推荐

    常用算法设计方法

    以上介绍了两种常用的算法设计方法:迭代法和穷举搜索法。这两种方法各有特点,适用于不同的问题场景。在实际应用中,选择合适的算法设计方法能够显著提高问题求解的效率和准确性。此外,对于更加复杂的问题,还可以...

    常用算法设计方法+搜集常用算法设计方法+搜集

    本文主要探讨几种常见的算法设计方法,包括迭代法、穷举搜索法,以及它们在实际问题中的应用。 1. 迭代法: 迭代法是一种通过不断更新变量的值来逼近解的方法,广泛应用于求解方程或方程组的近似根。对于单个方程 f...

    算法分析与设计课件:穷举法.ppt

    穷举法,也称为全搜索法,是一种基础的算法设计方法,主要用于寻找问题的所有解或者最优解。在解决货郎担问题的例子中,穷举法通过列举所有可能的城市排列组合来找出最短的路线。当城市数量为n时,路线的总数为(n-1)...

    软考常用算法设计方法

    本文将探讨几种常见的算法设计方法,包括迭代法、穷举搜索法以及递推法等,以帮助考生理解和掌握这些方法。 1. **迭代法** 迭代法是求解方程或方程组近似根的常用方法。在迭代过程中,我们不断用新的近似值替换旧...

    常用算法设计方法 迭代法

    本文主要讨论了两种常见的算法设计方法:迭代法和穷举搜索法。 迭代法是一种通过不断重复某个计算过程来逼近目标值或解决复杂问题的方法。在求解方程或方程组的根时,迭代法尤其有用。例如,对于单个方程f(x) = 0,...

    算法设计与分析-穷举法、贪心法、分枝限界法讲稿

    穷举法,又称暴力搜索法,是一种最基本的算法设计策略。它的基本思想是对所有可能的情况进行逐一检查,直到找到问题的解或者确定没有解为止。 #### 应用场景 穷举法适用于问题规模较小的情况,当问题的解空间有限且...

    常用算法设计方法(word版)

    "常用算法设计方法(word版)"为初学者和算法设计爱好者提供了一个系统的算法设计方法概述,涵盖了迭代法、穷举搜索法、递推法、贪婪法、回溯法、分治法、动态规划法等多种常用的算法设计方法,并提供了 C 语言编写...

    +常用算法常用算法设计方法(一).pdf

    根据给定文件的信息,我们可以深入探讨两个核心的算法设计方法:迭代法与穷举搜索法。这两种方法在解决复杂问题时具有重要的应用价值,尤其是在数值分析、计算机科学以及工程领域。 ### 迭代法 迭代法是一种广泛...

    常用算法设计方法(C语言)

    标题和描述中提到的知识点主要包括:ACM竞赛、算法设计、数据结构、程序设计、计算机程序的结构、迭代法、穷举搜索法、递推法、贪婪法、回溯法、分治法、动态规划法、递归技术。下面我将详细介绍这些知识点。 首先...

    sjwtu算法分析与设计 穷举法 03

    【穷举法】,也称为全搜索法或枚举法,是一种基础的算法设计思想,主要通过对所有可能的解进行尝试来找到问题的正确答案。在本次实验中,我们运用穷举法解决了一个分配问题,目标是寻找一种分配方案,使得每个人分配...

    算法与程序设计穷举法.doc

    ### 算法与程序设计——穷举法 #### 一、教学目标 1. **知识与技能** - 认识穷举法在日常生活问题解决中的应用,并认识到利用计算机用穷举法解决问题的高效性。 - 了解穷举法的基本概念及用穷举法设计算法的基本...

    计算机专业常用算法设计方法

    计算机专业中的算法设计是解决问题的关键,它涉及到一系列的方法和技术,如迭代法、穷举搜索法、递推法、动态规划法等。这些方法各有特点,适用于不同的问题场景。 首先,迭代法是一种常见的算法设计手段,尤其在...

Global site tag (gtag.js) - Google Analytics