第七届蓝桥杯省赛B组整理

第一题:
煤球数目

有一堆煤球,堆成三角棱锥形。具体:
第一层放1个,
第二层3个(排列成三角形),
第三层6个(排列成三角形),
第四层10个(排列成三角形),
....
如果一共有100层,共有多少个煤球?

请填表示煤球总数目的数字。
注意:你提交的应该是一个整数,不要填写任何多余的内容或说明性文字。

思路:

这个题很好想,找出规律后,循环相加就行。

第一层放1个,第二层3个,第三层6个,第四层10个。

得出规律:array[i]=i+arr[i-1] (从i为1开始)

 1 #include<iostream>
 2 using namespace std;
 3 
 4 int arr[101];
 5 
 6 int  main()
 7 {
 8     int sum=0;
 9     for(int i=1;i<=100;i++){
10         arr[i]=i+arr[i-1];
11         sum+=arr[i];
12     }
13     cout<<sum<<endl;
14     return 0;
15 }
View Code

第二题:

生日蜡烛

某君从某年开始每年都举办一次生日party,并且每次都要吹熄与年龄相同根数的蜡烛。

现在算起来,他一共吹熄了236根蜡烛。

请问,他从多少岁开始过生日party的?

请填写他开始过生日party的年龄数。
注意:你提交的应该是一个整数,不要填写任何多余的内容或说明性文字。

思路:暴力求解他从几岁开始过生日的,若是他过完这次party刚好吹熄了236根蜡烛,则输出开始的年龄。否则不用判断这次的年龄起始点。

 1 #include<iostream>
 2 using namespace std;
 3 
 4 int main()
 5 {
 6     for(int i=1;i<100;i++){
 7         int sum=0;
 8         for(int j=i;sum<236;j++){
 9             sum+=j;
10             if(sum==236){
11                 printf("%d
",i);
12             }
13         }
14     }
15     return 0;
16 }
View Code

第三题:

凑算式

这个算式中A~I代表1~9的数字,不同的字母代表不同的数字。

比如:
6+8/3+952/714 就是一种解法,
5+3/1+972/486 是另一种解法。

这个算式一共有多少种解法?

注意:你提交应该是个整数,不要填写任何多余的内容或说明性文字。

思路:这个题可以暴力破解,就是遍历1~9,9个数字的全排列,看看哪一个序列满足情况,就记作一次。全排列可以用两种方法实现1、头文件algorithm中的next_permutation()函数遍历全排列。2、使用dfs遍历全排列。

next_permutation()

 1 #include<iostream>
 2 #include<algorithm>
 3 #include<string>
 4 using namespace std;
 5 
 6 int arr[10]={1,2,3,4,5,6,7,8,9};
 7 
 8 int main()
 9 {
10     int count=0;
11     do{
12         if(arr[0]+arr[1]*1.0/arr[2]+(arr[3]*100+arr[4]*10+arr[5])*1.0/(arr[6]*100+arr[7]*10+arr[8])==10.0)
13             count++;
14 
15     }while(next_permutation(arr,arr+9));
16     cout<<count<<endl;
17     return 0;
18 }
View Code

dfs()方法

 1 #include<iostream>
 2 #include<algorithm>
 3 #include<string>
 4 using namespace std;
 5 int arr[10],Count=0;
 6 bool used[10];
 7 
 8 void dfs(int step)
 9 {
10     if(step==9){
11         if(arr[0]+arr[1]*1.0/arr[2]+(arr[3]*100+arr[4]*10+arr[5])*1.0/(arr[6]*100+arr[7]*10+arr[8])==10.0)Count++;
12 
13     }
14     else{
15         for(int i=1;i<10;i++){
16             if(!used[i]){
17                 arr[step]=i;
18                 used[i]=true;
19                 dfs(step+1);
20                 used[i]=false;
21             }
22         }
23     }
24 }
25 int main(){
26     dfs(0);
27     cout<<Count<<endl;
28     return 0;
29 }
View Code

第四题:

快速排序

排序在各种场合经常被用到。
快速排序是十分常用的高效率的算法。

其思想是:先选一个“标尺”,
用它把整个队列过一遍筛子,
以保证:其左边的元素都不大于它,其右边的元素都不小于它。

这样,排序问题就被分割为两个子区间。
再分别对子区间排序就可以了。

下面的代码是一种实现,请分析并填写划线部分缺少的代码。

注意:只填写缺少的内容,不要书写任何题面已有代码或说明性文字。

思路快速排序无论用什么方法,都是要完成确认基准点左边都是比他小的数据,右面的元素都是比它大的数据(升序的情况)。判断好基准点,头脑中模拟一下就能想明白。

 1 #include <stdio.h>
 2 
 3 void swap(int a[], int i, int j)
 4 {
 5 int t = a[i];
 6 a[i] = a[j];
 7 a[j] = t;
 8 }
 9 
10 int partition(int a[], int p, int r)
11 {
12 int i = p;
13 int j = r + 1;
14 int x = a[p];
15 while(1){
16 while(i<r && a[++i]<x);
17 while(a[--j]>x);
18 if(i>=j) break;
19 swap(a,i,j);
20 }
21 ___swap(a,j,p)___________________;
22 return j;
23 }
24 
25 void quicksort(int a[], int p, int r)
26 {
27 if(p<r){
28 int q = partition(a,p,r);
29 quicksort(a,p,q-1);
30 quicksort(a,q+1,r);
31 }
32 }
33 
34 int main()
35 {
36 int i;
37 int a[] = {5,13,6,24,2,8,19,27,6,12,1,17};
38 int N = 12;
39 
40 quicksort(a, 0, N-1);
41 
42 for(i=0; i<N; i++) printf("%d ", a[i]);
43 printf("
");
44 
45 return 0;
46 }
View Code

第五题:

抽签

X星球要派出一个5人组成的观察团前往W星。
其中:
A国最多可以派出4人。
B国最多可以派出2人。
C国最多可以派出2人。
....

那么最终派往W星的观察团会有多少种国别的不同组合呢?

下面的程序解决了这个问题。
数组a[] 中既是每个国家可以派出的最多的名额。
程序执行结果为:
DEFFF
CEFFF
CDFFF
CDEFF
CCFFF
CCEFF
CCDFF
CCDEF
BEFFF
BDFFF
BDEFF
BCFFF
BCEFF
BCDFF
BCDEF
....
(以下省略,总共101行)

 1 #include <stdio.h>
 2 #define N 6
 3 #define M 5
 4 #define BUF 1024
 5 
 6 void f(int a[], int k, int m, char b[])
 7 {
 8     int i,j;
 9     if(k==N){ 
10         b[M] = 0;
11         if(m==0) printf("%s
",b);
12         return;
13     }
14     
15     for(i=0; i<=a[k]; i++){
16         for(j=0; j<i; j++) b[M-m+j] = k+'A';
17         f(a,k+1,m-i,b);  //填空位置
18     }
19 }
20 int main()
21 {    
22     int  a[N] = {4,2,2,1,1,3};
23     char b[BUF];
24     f(a,0,M,b);
25     return 0;
26 }
View Code

仔细阅读代码,填写划线部分缺少的内容。

注意:不要填写任何已有内容或说明性文字。

 思路:k代表哪一个国家提供的人数,m表示总共还需要的人数,i为本次给它分配的人数。 

   每次递归轮到下一个国家出人。

第六题:

方格填数

如下的10个格子

填入0~9的数字。要求:连续的两个数字不能相邻。
(左右、上下、对角都算相邻)

一共有多少种可能的填数方案?

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

思路:

可以用dfs遍历查看可以满足条件的情况有多少。

这里的L代表行,H代表列。

注意判断好条件:

当前位置是now,判断now位置是否可以,要判断画斜线的单元格相差的绝对值不为1.。

注意判断递归的下一个位置。

 1 #include<iostream>
 2 #include<cstring>
 3 #include<cmath>
 4 using namespace std;
 5 int arr[5][6],count=0;
 6 bool used[10];
 7 
 8 bool jude(int l,int h,int x)
 9 {
10     if(abs(arr[l-1][h-1]-x)==1)return true;
11     if(abs(arr[l-1][h]-x)==1)return true;
12     if(abs(arr[l][h-1]-x)==1)return true;
13     if(abs(arr[l-1][h+1]-x)==1)return true; 
14     
15     return false;
16 
17 }
18 void dfs(int l,int h)
19 {
20     if(l==3&&h==4){
21         count++;
22         return;
23     }
24     else{
25         for(int x=0;x<10;x++){
26                 if(!jude(l,h,x)&& !used[x]){                                    
27                     arr[l][h]=x;
28                     used[x]=true;
29                     if(h<4){
30                         dfs(l,h+1);
31                     }
32                     else if(h==4){
33                         dfs(l+1,1);
34 
35                     }
36                     used[x]=false;
37                     }
38                 }
39     }
40 }
41 
42 int main()
43 {
44     memset(arr,0x3f,sizeof(arr));
45     //for(int i=0;i<5;i++)cout<<ends<<arr[0][i];
46     dfs(1,2);
47     printf("%d
",count);
48     return 0;
49 }
View Code

第七题:

剪邮票

如【图1.jpg】, 有12张连在一起的12生肖的邮票。
现在你要从中剪下5张来,要求必须是连着的。
(仅仅连接一个角不算相连)
比如,【图2.jpg】,【图3.jpg】中,粉红色所示部分就是合格的剪取。

请你计算,一共有多少种不同的剪取方法。

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

                 图1                    图2             图3

这个题刚开始想用dfs做,边判断边选格子,后来觉得这样做不行,错过了很多种情况,主要的原因是探测的方格情况只有一种,一旦回溯过去的路径就再也回不去了,于是参照着网上博友的写法重新又思考了一遍。https://blog.csdn.net/u014552756/article/details/50946197(博友博客),他主要用的方法是先选格子,之后再判断格子是否合法。

 1 #include<iostream>
 2 #include<cstring>
 3 using namespace std;
 4 
 5 int mp[12]={1,2,3,4,6,7,8,9,11,12,13,14};
 6 int aa[5],vis[5],sum=0;
 7 int b[4]={-1,1,-5,5};//左右上下
 8 
 9 void dfs(int n)
10 {
11     for(int i=0;i<4;i++){
12         int v=aa[n]+b[i];
13         for(int j=1;j<5;j++){
14             if(!vis[j]&&v==aa[j]){
15                 vis[j]=true;
16                 dfs(j);
17             }
18         }
19     }
20 }
21 
22 int main()
23 {
24     int count=0;
25     for(int a=0;a<12;a++)
26         for(int b=a+1;b<12;b++)
27             for(int c=b+1;c<12;c++)
28                 for(int d=c+1;d<12;d++)
29                     for(int e=d+1;e<12;e++){
30                         aa[0]=mp[a];
31                         aa[1]=mp[b];
32                         aa[2]=mp[c];
33                         aa[3]=mp[d];
34                         aa[4]=mp[e];
35                         memset(vis,0,sizeof(vis));
36                         vis[0]=1;
37                         dfs(0);
38                         int flag=0;
39                         for(int i=0;i<5;i++){
40                             if(!vis[i]){
41                                 flag=1;
42                             }
43                         }
44                         if(!flag)count++;
45 
46                     }
47     cout<<count<<endl;
48     return 0;
49 }
View Code

第八题:暂时不会

第九题:

交换瓶子

有N个瓶子,编号 1 ~ N,放在架子上。

比如有5个瓶子:
2 1 3 5 4

要求每次拿起2个瓶子,交换它们的位置。
经过若干次后,使得瓶子的序号为:
1 2 3 4 5

对于这么简单的情况,显然,至少需要交换2次就可以复位。

如果瓶子更多呢?你可以通过编程来解决。

输入格式为两行:
第一行: 一个正整数N(N<10000), 表示瓶子的数目
第二行:N个正整数,用空格分开,表示瓶子目前的排列情况。

输出数据为一行一个正整数,表示至少交换多少次,才能完成排序。

例如,输入:
5
3 1 2 5 4

程序应该输出:
3

再例如,输入:
5
5 4 3 2 1

程序应该输出:
2

资源约定:
峰值内存消耗 < 256M
CPU消耗 < 1000ms

思路:

 1 #include<iostream>
 2 using namespace std;
 3 
 4 const int maxn=10000+1000;
 5 int main()
 6 {
 7     int arr[maxn];
 8     int n;
 9     scanf("%d",&n);
10     for(int i=0;i<n;i++){
11         scanf("%d",arr+i);
12     } 
13     int ans=0;
14     for(int i=0;i<n-1;i++){
15         int Min=arr[i],index=i;
16         for(int j=i+1;j<n;j++){
17             if(Min>arr[j])Min=arr[j],index=j;
18         }
19         if(index!=i){
20             swap(arr[index],arr[i]);
21             ans++;
22         }
23     }
24     cout<<ans<<endl;
25     return 0;
26 }
View Code

第十题:暂时不会

 

原文地址:https://www.cnblogs.com/habit2021/p/12237815.html