转贴 : 枚举算法

来源:互联网 发布:linux lnmp搭建 编辑:程序博客网 时间:2024/05/19 05:31

枚举算法

[算法分析]
     HI,everybody.今天说的是枚举。
     什么是枚举? 枚者,一个一个也。 举者,列举也。 In a word,枚举就是一个一个地列举。 应用到程序中,枚举有许多表现形式,比如把所有的组合都扫描一遍,找出符合要求的组合。举个简单的例子,找素数。1什么都不是,2是素数,3是,4不是,5是……,如此把所有的自然数(当然是不可能的,只能尽量多)都找一遍,就能找出所有的素数(天大的乌托邦,呵。)。可以这么说,枚举是最简单,最基础,也是最没效率的算法,但是。枚举拥有很多优点,以致于他能够活到现在而不被淘汰。首先,枚举有超级无敌准确性,只要时间足够,正确的枚举得出的结论是绝对正确的。其次,枚举拥有天下第一全面性,因为它是对所有方案的全面搜索,所以,它能够得出所有的解。例:找偶数。(?!弱不弱智一点啊!没办法,太难你们不会,没准我也不会。)
  program oushu; {别忘了那个讨厌的 ; 哦}
  var i:integer;
  begin
     for i:=0 to 30000 do {为什么要30000呢?还记得吗?integer类型是从-32767到+32767之间的                                                整数,如果你要再大一点,可以用longint类型的}
             if i mod 2=0 then writeln (i); {i mod 2表示i给2除之后的余数,如9 mod 2=1,5 mod 7=5}
    end.{注意这里是"."哦}
     完了,就是这么简单,也许不用我说你就知道是什么意思,就是把0-30000之间的整数都找一次,如果它能够被2整除,就打印出来,如果不能就不打。
     热完身之后来点难一点的,就是刚才那道求素数。我们先来分析一下,一个整数n如果是素数那它有什么特征?哦,它只能够被1还有它本身整除。所以除了1和n之外,其它的从2到n-1之间的整数,都必须不能整除n。那么我们就取一个n,造一个循环语句,判断从2到n-1之间的整数中,有没有能整除n的,有的话,哪怕只有一个,那n都不是素数。懂了吗?也许有的朋友已经开始骂我笨了,没错,上面那个方法,确实有许多可以偷懒的地方,编程的一个大原则就是能有多懒就要多懒(当然是要在正确的前提下了。)还是不要叫懒吧,叫它优化,一个程序的效率,就取决于算法的好坏,一个好的高效率的算法和一个低效率的算法,所需要的时间相差很大,有时是一个只要几秒而另一个却要几千年。还是上面的例子:
     1、比n的平方根还大的整数,当然不能整除n。所以,这一部分我们不用管它。
     2、如果从2到int (sqrt(n))之间有一个数能整除n,那我们对n的判断就应该结束了而没必要再判断下面的数。
     3、你想一下如果一个数不能被2整除,那它还能够被4,被6,被8等等的2的倍数整除吗?当然不能。所以,我们又得出了一个结论。只要一个数n不能被所有的从2到int(sqrt(n))之间的素数整除,那它就一定是素数。
     这样,我们就把这个问题的算法,优化了不少。程序我就不写了,你自己看着办,值得一提的是我所说的第三个优化的方法所涉及的数据结构略微复杂了一点,如果初学者能力不足,那只用前面两个优化的方法也行,如果还有别的什么好的优化方法,也请MAIL给我。世界上有许多超级电脑都在试图寻找出世界上已知的最大的素数(已经证明了最大的素数是不存在的),所以没准你那个方法能够帮那些超级电脑一把。
     总结一下,枚举就是在全集中的元素一个一个拿出来试,有点象小孩数糖果,由于它的运算量相对较大,所以,我们应该注意尽可能地限制一些无谓运算的出现,这是搜索所要求的最重要的技巧,以后我们还会陆续地介绍其他一些减少运算量的方法。

[参考程序]
program  meiju;{枚举法求N以内素数}
const n=8;
var a:array[1..n] of integer; i,j,k:integer;
begin
     write(2);
     for i:=3 to n do
     begin
          j:=2; 
           k:=int(sqrt(i));
           while (j<=k) and (i mod j<>0)  do j:=j+1;
           if j<=k then write(i:4);
     end;
     writeln;
end.

[习题]
1、发奖品问题:学期末班里评出5位三好生。老师要将5件互不相同的奖品发给这5位同学。一共有哪几种不同的发法?
2、百钱买百鸡问题:有一个人有一百块钱,打算买一百只鸡。到市场一看,大鸡三块钱一只,小鸡一块钱三只,不大不小的鸡两块钱一个。现在,请你编一程序,帮他计划一下,怎么样买法,才能刚好用一百块钱买一百只鸡?
info:
writer: 周俊辉 downloader: LHEZ

原创粉丝点击