蓝桥杯:在计算机编程领域,是具有一定含金量的竞赛,用于选拔信息技术人才。

一般分为多个领域,其中包含了C/C#/C++/Java/Python等编程语言的测试题,多为算法的设计题。

下面,在搜题过程中,整理了一些比较有意思的原题,用于提高算法设计技巧。

注意:这里给出的答案不唯一,且为C/C++试题及解析!

题目:

第一题:煤球数目


有一堆煤球,堆成三角棱锥形。具体:

第一层放1个,

第二层3个(排列成三角形),

第三层6个(排列成三角形),

第四层10个(排列成三角形),

....

如果一共有100层,共有多少个煤球?



请填表示煤球总数目的数字。

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


读懂出题者的意图和考察目标:

1、  能不能识破递推规律。显然,这是一个递推(数列)类型的问题。

2、  是否掌握递推法。基本递推法是:后一项是前面若干项的计算。

3、  是否掌握递推法的C语言的实现。程序=算法+数据。这个问题的算法,是一个简单的for循环。这个问题中的数据是整型,但是,有些问题的计算过程和计算结果是浮点型。所以,在这一点要特别小心。每次期末考试,很多人都因为这个原因而扣分。

4、  是否具有细节观察和理解能力。“一堆煤球”、“三角棱锥形”,“请填表示煤球总数目的数字”、“注意:你提交的应该是一个整数,不要填写任何多余的内容或说明性文字”,等等,这些都需要考生具有很好的细节观察和理解能力。每次考试时,总是看到有些考生不按照规定答题。

5、  是否具有基本的高中数学功底。“有一堆煤球,堆成三角棱锥形”,这是一个立体的棱锥,题目还特意地在下面强调,“第二层3个(排列成三角形)”、“第三层6个(排列成三角形)”……

源代码:

1 #include<stdio.h>
 2 int main()
 3 {
 4     int a[101] ={0};
 5     for(int i = 1 ; i < 101 ; i ++)
 6         a[i] = a[i-1] + i;
 7     int ans = 0;
 8     for(int j = 1 ; j < 101 ; j ++)
 9         ans += a[j];
10     printf("%d\n",ans);
11     return 0;
12 }

 

第二题:生日蜡烛


某君从某年开始每年都举办一次生日party,并且每次都要吹熄与年龄相同根数的蜡烛。现在算起来,他一共吹熄了236根蜡烛。请问,他从多少岁开始过生日party的?


请填写他开始过生日party的年龄数。

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


读懂出题者的意图和考察目标:

1、 这同样是一个递推问题。

2、 递推方法。有变化:有限制。

3、 递推的实现。所以代码实现就要反映出这个变化来。

4、 所以直接用枚举法。start, end分别表示他开始过生日的年龄和今年的年龄,然后计算之间吹蜡烛的总和,如果等于236就输出start, end.

源代码:

1 #include<stdio.h>
 2 int main()
 3 {
 4     int start, end; //年龄的下限和上限
 5     for (start = 1; start < 236; start++) //年龄的下限的取值范围
 6     {
 7         for (end = start; end < 236; end++) //年龄上限的取值范围
 8         {
 9             int sum = 0;
10             for(int i = start; i <= end; i++) //年龄下、上限的和
11                 sum += i;
12             if( sum == 236)
13             {
14                 printf("start: %d end: %d\n", start, end);
15             }
16         }
17     }
18     return 0;
19 }

 

第三题:交换瓶子


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


比如有5个瓶子:

2 1 3 5 4


要求每次拿起2个瓶子,交换它们的位置。

经过若干次后,使得瓶子的序号为:

1 2 3 4 5


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


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


输入格式为两行:

第一行: 一个正整数NN<10000, 表示瓶子的数目

第二行:N个正整数,用空格分开,表示瓶子目前的排列情况。


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


例如,输入:

5

3 1 2 5 4


程序应该输出:

3


再例如,输入:

5

5 4 3 2 1


程序应该输出:

2


资源约定:

峰值内存消耗 < 256M

CPU消耗 < 1000ms


请严格按要求输出,不要画蛇添足地打印类似:“请您输入...的多余内容。


所有代码放在同一个源文件中,调试通过后,拷贝提交该源码。


注意: main函数需要返回0

注意: 只使用ANSI C/ANSI C++ 标准,不要调用依赖于编译环境或操作系统的特殊函数。

注意: 所有依赖的函数必须明确地在源文件中 #include <xxx>不能通过工程设置而省略常用头文件。


提交时,注意选择所期望的编译器类型。


贪心法,从左向右如果当前第i个瓶子编号不是i就把编号为i的瓶子换过来。

因为这里的n规模为10000,如果在交换的时候去用for找编号为i的瓶子在哪儿时间复杂度为O(n^2)会超时。

所以这里要用两个数组,一个数组是记录第i个瓶子编号为多少,一个是记录编号为i的瓶子在哪儿。注意我们在交换的时候要把这两个数组都维护!

源代码:

1 #include <stdio.h>
 2 #include <math.h>
 3 int arr[10010];
 4 int flag[10010];
 5 int main()
 6 {
 7     int ans = 0;
 8     int n,i;
 9     scanf("%d",&n);
10     for(i = 1 ; i <= n ; i ++) scanf("%d",&arr[i]);
11     for(i = 1 ; i <= n ; i ++ )flag[arr[i]] = i;
12     for(i = 1 ; i <= n ; i ++)
13     {
14         if( i != arr[i] )
15         {
16             int x = arr[i];
17             arr[i] ^= arr[flag[i]] ^= arr[i] ^= arr[flag[i]];
18             flag[i] ^= flag[x] ^= flag[i] ^= flag[x];
19             ans ++;
20         }
21     }
22     printf("%d\n",ans);
23     return 0;
24 }
25

 

小结:

1.在计算机编程中,数学是很重要的,数学用于算法的设计,要有很强的逻辑性,除了算法,其他的界面设计也要有一定的逻辑性(即不能反人类行为)。

2.在设计相关算法时,要充分理解题意,即条件桩和结果,如何优化算法等。

3.在学习编程的时候,编程语言(C/C#/C++/Java/Python)等它们之间是有相互联系的,主要是编程工具的开发环境,包和类,接口的部分区别,C语言是最基本的编程语言,即入门语言,新兴起的Python语言,是基于人工智能的编程语言,个人认为,Python语言是最简单易学的编程语言。因此,在编程语言的选择上,并不需要过度纠结它们的好坏,主要是了解核心算法,编程主要为算法设计,编程语言只是实现它的一种方式。