枚举算法,就是根据所提出的问题,列出该问题所有可能的解,并在列出解的过程中逐一的检查这个解是否是符合条件的可行解。
如果是就采纳这个解,如果不是就判断下一个。
枚举算法的思想比较直观,容易理解。但是要逐一的检查所有可能的解,所以效率比较低。
能够使用枚举算法的题目往往是最简单的一类题目。这类题目具有一下特点:
- 解枚举范围是有穷的
- 检查条件是确定的
一个简单的例子
题目来源
2016第七届蓝桥杯C/C++语言省赛A组第一题
问题描述
某君新认识一网友。
当问及年龄时,他的网友说:
“我的年龄是个2位数,我比儿子大27岁,
如果把我的年龄的两位数字交换位置,刚好就是我儿子的年龄”
请你计算:网友的年龄一共有多少种可能情况?
提示:30岁就是其中一种可能哦.
请填写表示可能情况的种数。
注意:你提交的应该是一个整数,不要填写任何多余的内容或说明性文字。
解决思路:
某人的年龄是两位数,不妨记为(a,b),其中a为十位,b为各位,根据题意则有:
条件1:1<=a<=9 && 0<=b<=9
条件2:10*a + b == 10*b + a + 27
接下来,我们就可以暴力枚举了!
代码
int main()
{
int a,b;
for(int a =1;a<=9;a++)
for(int b=0;b<=9;b++){
if(10*a+b == 10*b+a+27)
cout<<10*a+b<<" "<<10*b+a<<endl;
}
return 0;
}
一共7种可能性。
至此,枚举算法的代码结构就非常清晰。
枚举算法的代码结构就是:
枚举范围循环+条件判断语句
比如,这是水仙花数的枚举算法代码
//水仙花数枚举算法
int main()
{
int i,j,k;
for(int i=1;i<=9;i++)
for(int j=0;j<=9;j++)
for(int k=0;k<=9;k++){
if(i*i*i + j*j*j + k*k*k == 100*i+10*j+k)
cout<<100*i+10*j+k<<endl;
}
return 0;
}
接下来,笔者要进行简单的枚举算法的训练,做一些枚举算法的题。
枚举n到m之间所有质数
线性素数筛一遍过
#include<string.h>
//枚举[n,m]区间的素数
int prime[10001];
int main()
{
memset(prime,0,sizeof(prime));
prime[0] = 1;prime[1] = 1;prime[2] = 0;
//0表示素数,1表示不是素数
for(int c=2;c*c<=10001;c++){
if(prime[c]==0){
for(int i=2;i*c<=10001;i++)
prime[c*i] = 1;//倍数不是素数
}
}
int m,n;
cin>>m>>n;
for(int i=m;i<=n;i++){
if(!prime[i])
cout<<i<<endl;
}
return 0;
}
回文数字
//枚举5位或者6位的试题
//获取一个整数n的每位数字之和
int getsum(int n)
{
if(n == 0)
return 0;
int ret = 0;
while(n){
ret += n%10;
n = n/10;
}
return ret;
}
//判断一个数字是否为回文数
bool ishuiwen(int n)
{
int m = n;
int newn = 0;
int temp;
while(m){
newn *= 10;
temp = m%10;
newn += temp;
m = m/10;
}
return newn == n;
}
int main()
{
int sum,flag=0;
cin>>sum;
for(int i=10000;i<=999999;i++)
if(getsum(i)==sum && ishuiwen(i)){
flag = 1;
cout<<i<<endl;
}
if(!flag)//如果没有满足条件的的数字
cout<<-1<<endl;
return 0;
}
四平方和
//四平方和
int main()
{
int m;
cin>>m;
int a,b,c,d;
for(a=0;4*a*a<=m;a++)
for(b=a;a*a+3*b*b<=m;b++)
for(c=b;a*a+b*b+2*c*c<=m;c++)
for(d=c;a*a+b*b+c*c+d*d<=m;d++){
if(a*a+b*b+c*c+d*d == m){
cout<<a<<" "<<b<<" "<<c<<" "<<d<<endl;
return 0;
}
}
}
装饰效果
#include<iostream>
#include<stdio.h>
#include<stdlib.h>
#include<algorithm>
using namespace std;
int a[1001];
int getsum(int s,int e)
{
int sum = 0;
for(int i=s;i<=e;i++)
sum += a[i];
return sum;
}
int main()
{
int n;
cin>>n;
for(int i=1;i<=n;i++)
cin>>a[i];
int bestv = a[1];
for(int i=1;i<=n;i++)
for(int j=i;j<=n;j++)
if(bestv < getsum(i,j))
bestv = getsum(i,j);
if(bestv <= 0)
bestv = 0;
cout<<bestv<<endl;
return 0;
}
寒假作业
问题描述
本题是2015年第六届蓝桥杯省赛C/C++语言A组第六题真题
现在小学的数学题目也不是那么好玩的。
看看这个寒假作业:
□ + □ = □
□ - □ = □
□ × □ = □
□ ÷ □ = □
每个方块代表1~13中的某一个数字,但不能重复。
比如:
6 + 7 = 13
9 - 8 = 1
3 * 4 = 12
10 / 2 = 5
以及:
7 + 6 = 13
9 - 8 = 1
3 * 4 = 12
10 / 2 = 5
就算两种解法。(加法,乘法交换律后算不同的方案)
你一共找到了多少种方案?
请填写表示方案数目的整数。
注意:你提交的应该是一个整数,不要填写任何多余的内容或说明性文字。
暴力枚举代码
#include<iostream>
#include<stdio.h>
#include<stdlib.h>
#include<algorithm>
#include<string.h>
#include<math.h>
#include<inttypes.h>
using namespace std;
int a[13];
bool ishefa()
{
if(a[1]>=1 && a[1]<=13 && a[1]!=a[2] && a[1]!=a[3] && a[1]!=a[4] && a[1]!=a[5] && a[1]!=a[6] && a[1]!=a[7] && a[1]!=a[8] && a[1]!=a[9] && a[1]!=a[10] && a[1]!=a[11] && a[1]!=a[12])
if(a[2]>=1 && a[2]<=13 && a[2]!=a[3] && a[2]!=a[4] && a[2]!=a[5] && a[2]!=a[6] && a[2]!=a[7] && a[2]!=a[8] && a[2]!=a[9] && a[2]!=a[10] && a[2]!=a[11] && a[2]!=a[12])
if(a[3]>=1 && a[3]<=13 && a[3]!=a[4] && a[3]!=a[5] && a[3]!=a[6] && a[3]!=a[7] && a[3]!=a[8] && a[3]!=a[9] && a[3]!=a[10] && a[3]!=a[11] && a[3]!=a[12])
if(a[4]>=1 && a[4]<=13 && a[4]!=a[5] &&a[4]!=a[6] && a[4]!=a[7] && a[4]!=a[8] && a[4]!=a[9] && a[4]!=a[10] && a[4]!=a[11] && a[4]!=a[12])
if(a[5]>=1 && a[5]<=13 && a[5]!=a[6] && a[5]!=a[7] && a[5]!=a[8] && a[5]!=a[9] && a[5]!=a[10] && a[5]!=a[11] && a[5]!=a[12])
if(a[6]>=1 && a[6]<=13 && a[6]!=a[7] && a[6]!=a[8] && a[6]!=a[9] && a[6]!=a[10] && a[6]!=a[11] && a[6]!=a[12])
if(a[7]>=1 && a[7]<=13 && a[7]!=a[8]&& a[7]!=a[9] && a[7]!=a[10] && a[7]!=a[11] && a[7]!=a[12])
if(a[8]>=1 && a[8]<=13 && a[8]!=a[9] && a[8]!=a[10] && a[8]!=a[11] && a[8]!=a[12])
if(a[9]>=1 && a[9]<=13 && a[9]!=a[10] && a[9] !=a[11] && a[9]!=a[12])
if(a[10]>=1 && a[10]<=13 &&a[10]!=a[11] &&a[10]!=a[12])
if(a[11]>=1 &&a[11]<=13 && a[11]!=a[12])
if(a[12]>=1 && a[12]<=13)
return true;
return false;
}
int main()
{
int sum = 0;
//a[1] + a[2] == a[9]
//a[3] - a[4] == a[10]
//a[5] * a[6] == a[11]
//a[7] / a[8] == a[12]
//每个数都在[1,13]且各不相同
for(a[1] = 1;a[1]<=13;a[1]++)
for(a[2] = 1;a[2]<=13;a[2]++)
for(a[3]=1;a[3]<=13;a[3]++)
for(a[4]=1;a[4]<=13;a[4]++)
for(a[5]=1;a[5]<=13;a[5]++)
for(a[6]=1;a[6]<=13;a[6]++)
for(a[7]=1;a[7]<=13;a[7]++)
for(a[8]=1;a[8]<=13;a[8]++){
a[9] = a[1] + a[2];
a[10] = a[3] - a[4];
a[11] = a[5] * a[6];
a[12] = a[7] / a[8];//还得判断a[7]能被a[8]整除
if(ishefa() && a[7]%a[8]==0){
sum++;
//输出这个解
cout<<a[1]<<"+"<<a[2]<<"="<<a[9]<<endl;
cout<<a[3]<<"-"<<a[4]<<"="<<a[10]<<endl;
cout<<a[5]<<"*"<<a[6]<<"="<<a[11]<<endl;
cout<<a[7]<<"/"<<a[8]<<"="<<a[12]<<endl;
cout<<endl;
}
}
cout<<sum<<endl;
return 0;
}
运行结果
1+8=9
13-6=7
2*5=10
12/3=4
1+8=9
13-6=7
2*5=10
12/4=3
1+8=9
13-6=7
3*4=12
10/2=5
1+8=9
13-6=7
3*4=12
10/5=2
1+8=9
13-6=7
4*3=12
10/2=5
1+8=9
13-6=7
4*3=12
10/5=2
1+8=9
13-6=7
5*2=10
12/3=4
1+8=9
13-6=7
5*2=10
12/4=3
1+8=9
13-7=6
2*5=10
12/3=4
1+8=9
13-7=6
2*5=10
12/4=3
1+8=9
13-7=6
3*4=12
10/2=5
1+8=9
13-7=6
3*4=12
10/5=2
1+8=9
13-7=6
4*3=12
10/2=5
1+8=9
13-7=6
4*3=12
10/5=2
1+8=9
13-7=6
5*2=10
12/3=4
1+8=9
13-7=6
5*2=10
12/4=3
6+7=13
9-1=8
2*5=10
12/3=4
6+7=13
9-1=8
2*5=10
12/4=3
6+7=13
9-1=8
3*4=12
10/2=5
6+7=13
9-1=8
3*4=12
10/5=2
6+7=13
9-1=8
4*3=12
10/2=5
6+7=13
9-1=8
4*3=12
10/5=2
6+7=13
9-1=8
5*2=10
12/3=4
6+7=13
9-1=8
5*2=10
12/4=3
6+7=13
9-8=1
2*5=10
12/3=4
6+7=13
9-8=1
2*5=10
12/4=3
6+7=13
9-8=1
3*4=12
10/2=5
6+7=13
9-8=1
3*4=12
10/5=2
6+7=13
9-8=1
4*3=12
10/2=5
6+7=13
9-8=1
4*3=12
10/5=2
6+7=13
9-8=1
5*2=10
12/3=4
6+7=13
9-8=1
5*2=10
12/4=3
7+6=13
9-1=8
2*5=10
12/3=4
7+6=13
9-1=8
2*5=10
12/4=3
7+6=13
9-1=8
3*4=12
10/2=5
7+6=13
9-1=8
3*4=12
10/5=2
7+6=13
9-1=8
4*3=12
10/2=5
7+6=13
9-1=8
4*3=12
10/5=2
7+6=13
9-1=8
5*2=10
12/3=4
7+6=13
9-1=8
5*2=10
12/4=3
7+6=13
9-8=1
2*5=10
12/3=4
7+6=13
9-8=1
2*5=10
12/4=3
7+6=13
9-8=1
3*4=12
10/2=5
7+6=13
9-8=1
3*4=12
10/5=2
7+6=13
9-8=1
4*3=12
10/2=5
7+6=13
9-8=1
4*3=12
10/5=2
7+6=13
9-8=1
5*2=10
12/3=4
7+6=13
9-8=1
5*2=10
12/4=3
8+1=9
13-6=7
2*5=10
12/3=4
8+1=9
13-6=7
2*5=10
12/4=3
8+1=9
13-6=7
3*4=12
10/2=5
8+1=9
13-6=7
3*4=12
10/5=2
8+1=9
13-6=7
4*3=12
10/2=5
8+1=9
13-6=7
4*3=12
10/5=2
8+1=9
13-6=7
5*2=10
12/3=4
8+1=9
13-6=7
5*2=10
12/4=3
8+1=9
13-7=6
2*5=10
12/3=4
8+1=9
13-7=6
2*5=10
12/4=3
8+1=9
13-7=6
3*4=12
10/2=5
8+1=9
13-7=6
3*4=12
10/5=2
8+1=9
13-7=6
4*3=12
10/2=5
8+1=9
13-7=6
4*3=12
10/5=2
8+1=9
13-7=6
5*2=10
12/3=4
8+1=9
13-7=6
5*2=10
12/4=3
64
所以答案为64