藍橋杯省賽訓練營——枚舉算法

枚舉算法,就是根據所提出的問題,列出該問題所有可能的解,並在列出解的過程中逐一的檢查這個解是否是符合條件的可行解。
如果是就採納這個解,如果不是就判斷下一個。

枚舉算法的思想比較直觀,容易理解。但是要逐一的檢查所有可能的解,所以效率比較低。

能夠使用枚舉算法的題目往往是最簡單的一類題目。這類題目具有一下特點:

  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

未完待續

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章