穷举法,或称为暴力破解法,其基本思路是:对于要解决的问题,列举出它的所有可能的情况,逐个判断有哪些是符合问题所要求的条件,从而得到问题的解。它也常用于对于密码的破译,即将密码进行逐个推算直到找出真正的密码为止。例如一个已知是四位并且全部由数字组成的密码,其可能共有10000种组合,因此最多尝试10000次就能找到正确的密码。理论上利用这种方法可以破解任何一种密码,问题只在于如何缩短试误时间。因此有些人运用计算机来增加效率,有些人辅以字典来缩小密码组合的范围。
水仙花数
所谓的水仙花数是指:一个三位数,其各个位上的数字的立方和等于该数本身。可见水仙花数介于100到999之间
分析
方法一
设bai ,shi,ge表示这三位数的百位,十位,个位则这三位数ans=bai*100+shi*10+ge
满足以下条件的ans为所求所数
bai=1~9;shi=0~9;ge=0~9
ans==bai3+shi3+ge3
#include<iostream>
#include<cmath>
using namespace std;
int main()
{
int bai,shi,ge,ans;
for (bai=1;bai<10;bai++)
{
for (shi=0;shi<10;shi++)
{
for(ge=0;ge<10;ge++)
{
ans=bai*100+shi*10+ge;
if (pow(bai,3)+pow(shi,3)+pow(ge,3)==ans)
{
cout<<ans<<endl;
}
}
}
}
}
方法二
设ans是所求的三位数,bai ,shi,ge表示这三位数的百位,十位,个位则这三位数ans=bai*100+shi*10+ge
满足以下条件的ans为所求所数
ans=100~999
将ans拆分成百位数bai=ans/100,十位数shi=ans/10%10,个位数ge=ans%10,找满足下列式子的ans==bai3+shi3+ge3
#include<iostream>
#include<cmath>
using namespace std;
int main()
{
int bai,shi,ge,ans;
for (ans=100;ans<1000;ans++)
{
bai=ans/100;
shi=ans/10%10;
ge=ans%10;
if (pow(bai,3)+pow(shi,3)+pow(ge,3)==ans)
{
cout<<ans<<endl;
}
}
}
百元百鸡
今有鸡翁一,值钱伍;鸡母一,值钱三;鸡雏三,值钱一。凡百钱买鸡百只,问鸡翁、母、雏各几何?
方法一
设鸡翁x、母y、雏z只,由题意可以知道满足下列两个等式的x,y,z为本题的解
x+y+z=100且5*x+3*y+z/3=100且x,y,z是非负整数
x,y,z可取的范围0~100
#include<iostream>
using namespace std;
int main()
{
int x,y,z;
for (x=0;x<=100;x++)
{
for (y=0;y<=100;y++)
{
for (z=0;z<=100;z++)
{
if (x+y+z==100&&5*x+3*y+z/3==100&&z%3==0)
{
cout<<x<<" "<<y<<" "<<z<<endl;
}
}
}
}
}
方法二
设鸡翁x、母y、雏z只,由题意可以知道满足下列两个等式的x,y,z为本题的解
x+y+z=100且5*x+3*y+z/3=100且x,y,z是非负整数
x可取的范围0~20
y可取的范围0~33
z可取的范围0~100
#include<iostream>
using namespace std;
int main()
{
int x,y,z;
for (x=0;x<=20;x++)
{
for (y=0;y<=33;y++)
{
for (z=0;z<=100;z++)
{
if (x+y+z==100&&5*x+3*y+z/3==100&&z%3==0)
{
cout<<x<<" "<<y<<" "<<z<<endl;
}
}
}
}
}
方法三
设鸡翁x、母y、雏z只,由题意可以知道满足下列两个等式的x,y,z为本题的解
x+y+z=100且5*x+3*y+z/3=100且x,y,z是非负整数
x可取的范围0~20
y可取的范围0~33
z=100-x-y;
#include<iostream>
using namespace std;
int main()
{
int x,y,z;
for (x=0;x<=20;x++)
{
for (y=0;y<=33;y++)
{
z=100-x-y;
if (5*x+3*y+z/3==100&&z%3==0)
{
cout<<x<<" "<<y<<" "<<z<<endl;
}
}
}
}
九宫图
九宫图,就是把1~9九个数字填到3×3,使其每一横坚斜之和都相等
4 9 2
3 5 7
8 1 6
分析
九宫图每格用九个变量a,b,c,d,e,f,g,h,i如下图
a b c
d e f
g h i
每一变量的取值范围为1~9
a+b+c=d+e+f=g+h+i=a+e+i=c+e+g=a+d+g=b+e+h=c+f+i
且每个数学恰好出现一次
砝码称重
现有1g、2g、3g、5g、10g、20g的砝码各若干枚,问用这些砝码可以称出多少种不同的重量。(设砝码的总重量不超过1000克,且砝码只能放在天平的一端)
分析
设1g,2g,3g,5g,10g,20g的砝码分别有a,b,c,d,e,f个。
取1g的砝码k1个 有0~a个
取2g的砝码k2个有0~b个
取3g的砝码k3个有0~c个
取5g的砝码k4个有0~d个
取10g的砝码k5个有0~e个
取20g的砝码k6个有0~f个
可称重量为k1+2*k2+3*k3+5*k4+10*k5+20*k6
分析
由于总重量为1000克,可以设置标识数数,当可以称的重量设为true
最后统计true的数量
//P2347 砝码称重
#include<iostream>
using namespace std;
int a1,a2,a3,a4,a5,a6;
const int tg[6]={1,2,3,5,10,20};
int ans[1001];
int main()
{
cin>>a1>>a2>>a3>>a4>>a5>>a6;
for (int i1=0;i1<=a1;i1++)
{
for (int i2=0;i2<=a2;i2++)
{
for (int i3=0;i3<=a3;i3++)
{
for (int i4=0;i4<=a4;i4++)
{
for (int i5=0;i5<=a5;i5++)
{
for (int i6=0;i6<=a6;i6++)
{
ans[i1*tg[0]+i2*tg[1]+i3*tg[2]+i4*tg[3]+i5*tg[4]+i6*tg[5]]=1;
}
}
}
}
}
}
int ans0=0;
for (int i=1;i<=1000;i++)
{
ans0+=ans[i];
}
cout<<"Total="<<ans0<<endl;
}
找钱
用10元和50元两种纸币组成240元,共有几种方法。
分析
设10元和50元两种纸币各x和y张,问题变化求方程10*x+50*y=240为负整数解的个数。
#include<bits/stdc++.h>
using namespace std;
int main()
{
int x,y,ans=0;
for (x=0;x<=240/10;x++)
{
for (y=0;y<=240/50;y++)
{
if (x*10+y*50==240) ans;
}
}
cout<<ans<<endl;
return 0;
}
枚举算法是我们在日常中使用到的最多的一个算法,它的核心思想就是:枚举所有的可能。
枚举法的本质就是从所有候选答案中去搜索正确的解,使用该算法需要满足两个条件:
(1)可预先确定候选答案的数量;
(2)候选答案的范围在求解之前必须有一个确定的集合。
程序结构 循环+选择语句
优点:算法简单,在局部地方使用枚举法,效果十分的好
缺点:运算量过大,当问题的规模变大的时候,循环的阶数越大,执行速度越慢
优化:减少枚举元素与范围
注意:不能遗漏,不要重复。