2025年05月01日 星期四 农历 乙巳年(蛇)四月初四

信息学奥赛常考算法——穷举法

发布人:钱翠萍    发布时间:2012-05-31 点击量:3982

★穷举法是基于计算机特点而进行解题的思维方法。

一般在一时找不出解决问题的更好的途径时,可以根据问题中的部分条件将所有可能解的情况列举出来,然后通过一一验证是否符合整个问题的求解要求,而得到问题的解。这种解决问题的方法我们称之为穷举算法。

穷举算法的特点是算法简单,但运行时所花费的时间量大。

穷举法通常用多重循环加条件语句来编写程序。

    穷举算法的模式:

    ⑴问题解的可能搜索的范围:用循环或循环语句来实现;

    ⑵写出符合问题解的条件;

    ⑶能使程序优化的语句,以便缩小搜索范围,减少程序运行时间。

典型例题:

    1、古希腊人认为因子的和等于它本身的数是一个完全数(自身因子除外),例如28的因子是124714,且1+2+4+7+14=28,28是一个完全数,编写一个程序求2∽1000内的所有完全数。

算法分析:

⑴本题是一个搜索问题,搜索范围是2-1000找出这个范围内的完全数。

⑵完全数必须满足的条件:因子的和等于该数的本身。

⑶细化分解因子和因子求和。

  program yinzi;

  var a,b,s:integer;

  begin

    for a:=2 to 1000 do

    begin

      s:=0;

     for b:=1 to a-1 do

       if a mod b =0 then s:=s+b; {分解因子并求和}

       if a=s then begin

         write(a,’=’,1);

     for b:=2 to a-1 do

        if a mod b=0 then write(‘+’,b);

     writeln;

     end;

   end;

  end.

2、邮局发行一套票面有四种不同的值的邮票,如果每份信所贴邮票张数不超过三枚,存在整数r,使得用不超过三枚的邮票,可以贴出连续的整数123···r来,找出这四种面值的数,使得r值最大。

算法分析:

⑴面值不同的四种邮票,每封信所贴邮票不超过3张。

⑵用这四种邮票贴出连续的整数,并且使r值最大。

⑶用穷举法找出所有符合条件的解。

⑷本题用集合的方法统计邮票的面值,提高判重的速度。

设四种邮票的面值分别为:abcd,根据题意设:a,因此a=1,用循环语句完成搜索。

program p12_3;

var a,b,c,d:integer;   {各种邮票可能取值}

    x,x0,x1,x2,x3,x4:integer;

    st1:set of 1..100;

function number(a,b,c,d:integer);integer;

var n1,n2,n3,n4,sum:integer;

begin

  st1:=[];

  for n1:=0 to 3 do   {每种邮票所取的张数}

    for n2:=0 to 3-n1 do

      for n3:=0 to 3-n1-n2 do

        for n4:=0 to 3-n1-n2-n3 do

          begin

            if n1+n2+n3+n4

              begin

                sum:=n1*a+n2*b+n3*c+n4*d;

                st1:=st1+[sum]

              end;

          end;

  sum:=1;

  while sum in st1 do sum:=sum+1;

  number:=sum-1;

end;

begin

  a:=1;  x0:=0;

  for b:=a+1 to 3*a+1 do

    for c:=b+1 to 3*b+1 do

      for d:=c+1 to 3*c+1 do

        begin

          x:=number(a,b,c,d);

          if x>x0 then

            begin

              x0:=x;

              x1:=a;

              x2:=b;

              x3:=c;

              x4:=d;

              write(x1:5,x2:5,x3:5,x4:5);

              writeln('':10,'x0=',x0);

            end;

        end;

end.