基础算法—枚举算法

一、枚举法的本质
     枚举法本质就是搜索算法,通过一一列通过暴力方式找出每一个符合情况的元素;枚举也称作       穷举,指的是从问题所有可能的解的集合中一一枚举各元素。

二、基本思想:
    用题目中给定的检验条件判定哪些是无用的,哪些是有用的。能使命题成立。即为其解。

三、优缺点:
    优点:算法简单,操作性强,在局部地方使用枚举法,效果会十分不错。
    缺点:运算量过大,当问题的规模变大的时候,循环的阶数越大,执行速度越慢(时间复杂度会升高)。

四、枚举框架

n=0;
for(k=<区间下限>;k<=<区间上限>;k++)    
                   // 控制枚举范围 
  if(<约束条件>)   // 根据约束条件实施筛选 
     { printf(<满足要求的解>);  // 输出解 
       n++;       // 统计解的个数 
     }

五、应用例题

1.枚举法计算最大公约数(通过对两个数中较小的数进行递归,逐一尝试求出符合条件的值)

int main()
{ long m,n,c;
  printf("请输入正整数m,n: ");
  scanf("%ld,%ld",&m,&n);	    // 输入正整数m,n 
  if(mn
  for(c=n;c>=1;c--)             // c枚举循环 
    if(m%c==0 && n%c==0) break; // 按定义判定        
  printf("(%ld,%ld)=%ld\n",m,n,c);   // 输出结果 
  }

2.统计与求和,要求计算并输出代数和四舍五入精确到小数点后第6位基础算法—枚举算法_第1张图片

例如对此公式的求和:

问题思路:我们能够发现分母能够被三整除的分式前为负号,不然则为正好

void main()
{ long n,k; double s=0;
  printf("  请输入正整数n: "); scanf("%ld",&n);     
  for(k=1;k<=n;k++)
    { if(k%3>0) s=s+1.0/k;    // 按k取值求代数和
      else s=s-1.0/k;      
    }
printf(“  s(%ld)=%.6f \n”,n,s); //输出结果
}

3.整数搜索佩尔方

例:搜索合数世纪

一个世纪的一百个年号中常存在有素数。例如,现在所处的21世纪的100个年号中存在2003,2011等14个素数。那么,是否存在一百个年号中没有素数的世纪?
其中我们定义:若一个世纪的100个年号中不存在素数,即100个年号全为合数的世纪称为合数世纪。
那么输入正整数m(约定m≤100),试探索前m个合数世纪。
思路分析: 设变量b统计合数世纪个数,设置条件循环,条件即为b 探索a世纪,从a=1开始递增1取值。设第a世纪的50个奇数年号(偶数年号无疑均为合数)为n,显然有:  a*100-99≤n≤a*100-1 设置n(a*100-99~a*100-1)循环,n步长为2,枚举a世纪奇数年号n; 设置k(3~)试商循环,k步长为2,应用试商判别年号n是否为素数: 若n为素数,退出试探下一个世纪; 若n为合数,并用变量s统计这50个n年号中的合数的个数。 对于a世纪,若s=50,即50个奇数都为合数,找到a世纪为合数世纪,用b++统计合数世纪的个数, 并打印输出第b个合数世纪为a 世纪,同时输出其年号范围。
代码:
#include 
#include 
void main()
{long a,n,k; int b,m,s,x;
 printf("  请确定m: "); scanf("%d",&m);   //探索前m个合数世纪
 a=1;b=0;
while (b

需要解释的是:

(1)for(k=3;k<=sqrt(n);k+=2) 是一个再嵌套循环语句,表示对变量k进行一系列赋值,并在每次赋值后执行再嵌套循环体内的代码。
(2)变量k的初始值是3,表示从3开始检验当前年号n是否能被整除。 变量k的终止条件是 k<=sqrt(n),表示只检验到当前年号n的平方根为止,因为如果n能被大于平方根的数整除,那么也一定能被小于平方根的数整除。

(3)变量k的增量是 k+=2,表示每次将变量k的值加2,相当于 k=k+2。这样做的目的是只考虑奇数因子,因为偶数因子一定能被2整除。

通过以上三个简单的例子我相信这个简单的算法就轻松拿捏了~

解佩尔

你可能感兴趣的:(算法分析,c++,数据结构,算法)