枚举算法(暴力法)板子

1.枚举算法的定义:
在进行归纳推理时,如果逐个考察了某类事件的所有可能情况,因而得出一般结论,那么该结论是可靠 的,这种归纳方法叫做枚举法,因其逐个考察的性质又称其为“暴力枚举法”,简称“暴力法”
2.枚举算法的思想是:
将问题的所有可能的答案一一列举然后根据条件判断此答案是否合适,保留合适的,舍弃不合适的。
3.使用枚举算法解题的基本思路如下:
(1)确定枚举对象、范围和判定条件。
(2)逐一枚举可能的解并验证每个解是否是问题的解。
4.枚举算法步骤:
(1)确定解题的可能范围,不能遗漏任何一个真正解,同时避免重复。
(2)判定是否是真正解的方法。
(3)为了提高解决问题的效率,使可能解的范围将至最小。

5.枚举算法的缺点:运算量比较大,接替效率不高。如果枚举的范围太大,在时间上就难以承受,会TLE。优点:思路简单,程序编写和调试方便。

枚举例题:(部分转载自网上)

1.完美立方问题

        a3 = b3 + c3 + d3 为完美立方等式。例如123 = 6^3 + 83 + 103。编写一个程序,对任意的正整数N(N≤100),寻找所有的四元组(a,b,c,d),使得a3 = b3 + c3 + d3,其中a > 1,b,c,d≤N。

#include<bits/stdc++.h>

int main()
{
    int i,n,a,b,c,d;
    scanf("%d",&n);//输入正整数n 
    for(a=2;a<=n;a++)
       for(b=2;b<=a-1;b++)
         for(c=b;c<=a-1;c++)
           for(d=c;d<=a-1;d++)
                if(a*a*a==b*b*b+c*c*c+d*d*d)
                printf("a=%d,b=%d,c=%d,d=%d\n",a,b,c,d);
    return 0;
}
此时答案用了三层嵌套,时间复杂度为O(n4)(即n的四次方),这是一种易得但是在数据超过一定范围会TLE的算法,在a,b,c,d很小时可以使用。

2.“高能”酒店

        小林在NOIP比赛期间住在“新世界”酒店。和其他酒店不一样的是,这个酒店每天都有一个高能的数字t,这个数字在楼层中是不会出现的,以t=3为例,则3、13、31、33等楼层是不存在的,楼层编号为1,2,4,5,……所以实际上的4楼才是3楼
已知小林预定了编号为m层的房间,并且当天高能数字是t,现在他想知道房间所在的真实楼层是多少,请你帮他解决这个问题。

#include<bits/stdc++.h>
using namespace std;
bool s(int a,int b){
  while(a!=0){
    if(a%10==b){
      return false;
    }
    a/=10;
  }
  return true;
}
int main(){
  int m,t,sum=0;
  cin>>m>>t;
  for(int i=1;i<=m;i++){
    if(s(i,t)){
      sum++;
    }
  }
  cout<<sum;
  return 0;
}

3.洛谷P1024 [NOIP2001 提高组] 一元三次方程求解(普及)  

有形如:a x^3 + b x^2 + c x + d = 0 这样的一个一元三次方程。给出该方程中各项的系数(a,b,c,d 均为实数),并约定该方程存在三个不同实根(根的范围在 -100 至 100 之间),且根与根之差的绝对值 ≥1。要求由小到大依次在同一行输出这三个实根(根与根之间留有空格),并精确到小数点后2位。

提示:记方程 f(x) = 0,若存在 2 个数 x1​ 和 x2​,且 x1 < x2​,f(x1​)×f(x2​)<0,则在 (x1​,x2​) 之间一定有一个根。(数学上的零点定理)

解题代码如下:
#include<bits/stdc++.h>
using namespace std;
double a,b,c,d;
int main(){
    scanf("%lf%lf%lf%lf",&a,&b,&c,&d); // 输入
    for(double i=-100;i<=100;i+=0.001){//枚举每个答案
        if(fabs(i*i*i*a+i*i*b+i*c+d)<0.0001)//避免double精度错误
            printf("%.02lf ",i);//两位小数输出
    }
    return 0;
}

4.洛谷P1151 子数整数(入门)

对于一个五位数a1​a2​a3​a4​a5​,可将其拆分为三个子数:

sub1​=a1​a2​a3​

sub2​=a2​a3​a4​

sub3​=a3​a4​a5​

例如,五位数2020720207可以拆分成

sub1​=202

sub2​=020(=20)

sub3​=207

现在给定一个正整数K,要求你编程求出10000到30000之间所有满足下述条件的五位数,条件是这些五位数的三个子数sub1​,sub2​,sub3​都可被K整除。

解题代码如下:

#include<bits/stdc++.h>
using namespace std;
int k;
int a,b,c;
int p;
int main()
{
cin>>k;
for(int i=10000; i<=30000; i++)//注意范围 
{
    a=i/10000*100+i/1000%10*10+i/100%10;
    b=i/1000%10*100+i/100%10*10+i/10%10;    
    c=i/100%10*100+i/10%10*10+i%10;//以上为重点公式 
    if(a%k==0&&b%k==0&&c%k==0)
    {
            cout<<i<<endl;
            p=1;
    }

}
if(p==0)cout<<"No";//被忘了输出No 
return 0;
}

                                       

  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

华梦天下

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值