枚举法

枚举法

数学与计算机算法术语
枚举法是利用计算机运算速度快、精确度高的特点,对要解决问题的所有可能情况,一个不漏地进行检验,从中找出符合要求的答案,因此枚举法是通过牺牲时间来换取答案的全面性。[1]在数学和计算机科学理论中,一个集的枚举是列出某些有穷序列集的所有成员的程序,或者是一种特定类型对象的计数。这两种类型经常(但不总是)重叠。
    中文名:枚举法 外文名:Enumeration method 所属学科: 定义:逐个考察了某类事件的所有可能 借助:计算机运算速度快精确度高特点 结构:while循环 算法:二进制加法,此时需要数组来帮忙

特点

将问题的所有可能的答案一一列举,然后根据条件判断此答案是否合适,合适就保留,不合适就丢弃。例如:找出1到100之间的素数,需要将1到100之间的所有整数进行判断。枚举算法因为要列举问题的所有可能的答案,所有它具备以下几个特点:

1、得到的结果肯定是正确的;

2、可能做了很多的无用功,浪费了宝贵的时间,效率低下。

3、通常会涉及到求极值(如最大,最小,最重等)。

4、数据量大的话,可能会造成时间崩溃。

结构

枚举算法的一般结构:while循环。

首先考虑一个问题:将1到100之间的所有整数转换为二进制数表示。

算法一

fori:=1to100dobegin

将i转换为二进制,采用不断除以2,余数即为转换为2进制以后的结果。一直除商为0为止。

end;

算法二

二进制加法,此时需要数组来帮忙。

programp;

vara:array[1..100]ofinteger;{用于保存转换后的二进制结果}

i,j,k:integer;

begin

fillchar(a,sizeof(a),0);{100个数组元素全部初始化为0}

fori:=1to100dobegin

k:=100;

whilea[k]=1dodec(k);{找高位第一个为0的位置}

a[k]:=1;{找到了立刻赋值为1}

forj:=k+1to100doa[j]:=0;{它后面的低位全部赋值为0}

k:=1;

whilea[k]=0doinc(k);{从最高位开始找不为0的位置}

write('(',i,')2=');

forj:=kto100dowrite(a[j]);{输出转换以后的结果}

writeln;

end;

end.

枚举法,常常称之为穷举法,是指从可能的集合中一一枚举各个元素,用题目给定的约束条件判定哪些是无用的,哪些是有用的。能使命题成立者,即为问题的解。

基本思路

采用枚举算法解题的基本思路:

(1)确定枚举对象、枚举范围和判定条件;

(2)枚举可能的解,验证是否是问题的解。

重点

用这种方法,很快就可以把程序编出来,再将样例数据代入测试也是对的,等成绩下来才发现这题没有全对,只得了一半的分。这种解法为什么是错的呢?错在哪里?前面的分析好象也没错啊,难道这题不能用枚举法做吗?看到这里大家可能有点迷惑了。

在上面的解法中,枚举范围和枚举对象都没有错,而是在验证枚举结果时,判定条件用错了。因为要保留二位小数,所以求出来的解不一定是方程的精确根,也许会正好离精确根差一点,再代入ax3+bx2+cx+d中,所得的结果也就不一定等于0,因此用原方程ax3+bx2+cx+d=0作为判断条件是不准确的。

我们换一个角度来思考问题,设f(x)=ax3+bx2+cx+d,若x为方程的根,则根据提示可知,必有f(x-0.005)*(x+0.005)<0,如果我们以此为枚举判定条件,问题就逆刃而解。另外,如果f(x-0.005)=0,那么就说明x-0.005是方程的根,这时根据四舍五入,方程的根也为x。(不用f(x+0.005)是由于这个问题是有下个循环解决)所以我们用(f(x-0.005)*f(x+0.005)<0)和(f(x-0.005)=0)作为判定条件。为了程序设计的方便,我们设计一个函数f(x)计算ax3+bx2+cx+d的值,程序如下:

{$N+}

var

k:integer;

a,b,c,d,x:extended;

functionf(x:extended):extended;{计算ax3+bx2+cx+d的值}

begin

f:=((a*x+b)*x+c)*x+d;

end;

begin

read(a,b,c,d);

fork:=-10000to10000do

begin

x:=k/100;

if(f(x-0.005)*f(x+0.005)<0)or(f(x-0.005)=0)thenwrite(x:0:2,'');{若x两端的函数值异号或x-0.005刚好是方程的根,则确定x为方程的根}

end;

end.

优缺点

缺点

用枚举法解题的最大的缺点是运算量比较大,解题效率不高,如果枚举范围太大(一般以不超过两百万次为限),在时间上就难以承受。但枚举算法的思路简单,程序编写和调试方便,比赛时也容易想到,在竞赛中,时间是有限的,我们竞赛的最终目标就是求出问题解,因此,如果题目的规模不是很大,在规定的时间与空间限制内能够求出解,那么我们最好是采用枚举法,而不需太在意是否还有更快的算法,这样可以使你有更多的时间去解答其他难题。

优点

由于枚举法一般是现实生活中问题的“直译”,因此比较直观,易于理解;枚举法建立在考察大量状态、甚至是穷举所有状态的基础上,所以算法的正确性比较容易证明。

优化

枚举法的时间复杂度可以用状态总数*考察单个状态的耗时来表示,因此优化主要是:

⑴减少状态总数(即减少枚举变量和枚举变量的值域)

⑵降低单个状态的考察代价

优化过程从几个方面考虑。具体讲

⑴提取有效信息

⑵减少重复计算

⑶将原问题化为更小的问题

⑷根据问题的性质进行截枝

⑸引进其他算法

相关词条

相关搜索

其它词条