蓝桥杯省赛训练营——枚举算法

枚举算法,就是根据所提出的问题,列出该问题所有可能的解,并在列出解的过程中逐一的检查这个解是否是符合条件的可行解。
如果是就采纳这个解,如果不是就判断下一个。

枚举算法的思想比较直观,容易理解。但是要逐一的检查所有可能的解,所以效率比较低。

能够使用枚举算法的题目往往是最简单的一类题目。这类题目具有一下特点:

  1. 解枚举范围是有穷的
  2. 检查条件是确定的

一个简单的例子

题目来源

2016第七届蓝桥杯C/C++语言省赛A组第一题

问题描述

某君新认识一网友。
当问及年龄时,他的网友说:
“我的年龄是个2位数,我比儿子大27岁,
如果把我的年龄的两位数字交换位置,刚好就是我儿子的年龄”

请你计算:网友的年龄一共有多少种可能情况?

提示:30岁就是其中一种可能哦.

请填写表示可能情况的种数。
注意:你提交的应该是一个整数,不要填写任何多余的内容或说明性文字。

解决思路:

某人的年龄是两位数,不妨记为(a,b),其中a为十位,b为各位,根据题意则有:

条件11<=a<=9 && 0<=b<=9
条件210*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

未完待续

发布了97 篇原创文章 · 获赞 101 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/practical_sharp/article/details/103961295
今日推荐