【ACM暑假培训】1、穷举算法

来源:互联网 发布:手机编辑图片大小软件 编辑:程序博客网 时间:2024/06/11 14:47

                          穷举算法


穷举,又叫枚举法,指的是从可能的解的集合中一一枚举各元素, 用题目给定的检验条件判定哪些是能使命题成立,即为其解。应用到程序中,枚举有许多表现形式,比如把所有的组合都扫描一遍,找出符合要求的组合。
举个简单的例子,找素数。1什么都不是,2是素数,3是,4不是,5是……,如此把所有的自然数(当然是不可能的,只能尽量多)都找一遍,就能找出所有的素数。
可以这么说,枚举是最简单,最基础,也是最没效率的算法,但是。枚举拥有很多优点,以致于他能够活到现在而不被淘汰。首先,枚举有超级无敌准确性,只要时间足够,正确的枚举得出的结论是绝对正确的。其次,枚举拥有天下第一全面性,因为它是对所有方案的全面搜索,所以,它能够得出所有的解。例:找偶数。
【题目一】把一元钞票换成一分、二分、五分硬币(每种至少一枚),有哪些种换法?
【答案】461种
提示:
for i:=1 to 93 do
for j:=1 to 47 do
for k:=1 to 19 do
if 100=i+2*j+5*k then n:=n+1;
还有没有效率更高的算法呢?留给大家考虑。

思路:

     这些本身超简单。。。。。

     因为要求硬币每种至少一枚,100-(1+2+5)=92,三种硬币只要凑出92就满足题意。

    从5硬币开始凑,有效减少循环次数。

   92减去5和2硬币面额得到的便是1分硬币的个数。

#include<stdio.h>void main(){int sum=0;for(int i=0;i<=20;i++){   for(int j=0;j<=50;j++)if(92-5*i-2*j>=0)   sum++;}printf("%d\n",sum);}


【题目二】将1,2...9共9个数分成三组,分别组成三个三位数,且使这三个三位数构成1:2:3的比例,试求出所有满足条件的三个三位数.

 

分析:这是1998年全国分区联赛普及组试题(简称NOIP1998pj,以下同)。此题数据规模不大,可以进行枚举,如果我们不加思地以每一个数位为枚举对象,一位一位地去枚举:

for a:=1 to 9 do

  for b:=1 to 9 do

   ………

    for i:=1 to 9  do

这样下去,枚举次数就有99次,如果我们分别设三个数为x,2x,3x,以x为枚举对象,穷举的范围就减少为93,在细节上再进一步优化,枚举范围就更少了。

思路:

     将x作为基准,计算2x、3x的值,再判断3组数的每一位是否都不相同即可。

#include<stdio.h>void main(){    int i,a,fal,n;   for(i=123;i<333;i++)   {       fal=0;   int flag[10]={0};   for(int j=1;j<=3;j++){   n=i*j;   while(n)   {          a=n%10;  if((flag[a]==0)&&(a!=0))  {  flag[a]=1;  n=n/10;  }      else  {         fal=1;     break;  }   }//while   if(fal==1)   break;   }   if(fal==0)   printf("%d %d %d\n",i,2*i,3*i);   }}


运行结果:

192 384 576

219 438 657

273 646 819

327 654 981


【题目三】:穷举法中穷举方案的选择

陈婷有一个E-MAIL邮箱的密码是一个5位数。但因为有一段比较长的日子没有打开这个邮箱了,陈婷把这个密码给忘了。不过陈婷自己是8月1日出生,而她妈妈的生日则是9月1日,她特别喜欢把同时是8l和9l的倍数用作密码。陈婷还记得这个密码的中间一位(百位数)是l。你能设计一个程序帮她找回这个密码吗?

本问题的数学模型是:

求出一个5位数,它的百位是l,而且它能同时被81和9l整除。

#include<stdio.h>void main(){   int n=99999/7371;   int x;   for(int i=1;i<=n;i++){    x=7371*i;        if(x>=10000&&x<100000&&(x/100%10==1))   printf("%d\n",x);   }}

运行结果:22113


原创粉丝点击