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

                          穷举算法


穷举,又叫枚举法,指的是从可能的解的集合中一一枚举各元素, 用题目给定的检验条件判定哪些是能使命题成立,即为其解。应用到程序中,枚举有许多表现形式,比如把所有的组合都扫描一遍,找出符合要求的组合。
举个简单的例子,找素数。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


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值