第十一届蓝桥杯软件类Python组(最新)(试题回忆+部分个人解答)

第二次参加蓝桥杯竞赛了,欢迎各位同学来一起交流~ 如果发现我的代码有什么问题的话,敬请指正(抱拳

PS:只记得每个题目的问题本质了,题目原文是怎么描述已经忘得差不多了。

第一题. 贴门牌号

原问题:从1到2020中这些数字中有多少个2(注意:不是问多少个数字里有2),

解题思路:基础题不赘述了哈,好像去年C++组的第一题也是这个呢,不过用Python写可真香

参考代码:

ans = 0
for i in range(1,2021):
    ans += (str(i).count('2'))
print(ans)

运行结果是624


第二题. 2020

原问题:在一个给定的由数字 '0' 和 '2' 组成的矩阵中寻找横向往右、纵向往下和斜向往右下的 '2020' 排列,原题中给定的矩阵是300行300列的,在一个txt文件中存放。

解题思路:同样数据量不大,暴力就完事了,考试时我还不知道怎么用python读取txt,只能在控制台手动输入,最后一行输入一个1作为结束标志。

参考代码:

def check(s):
    return s == '2020'
matrix = []
s = input()
while '1' not in s:
    matrix.append(list(s))
    s = input()
n,m = len(matrix),len(matrix[0])
ans = 0
for i in range(n):
    for j in range(m):
        if i + 3 < n and check(matri[i][j] + matrix[i+1][j] + matrix[i+2][j] + matrix[i+3][j]):
            ans += 1
        if j + 3 < m and check(matrix[i][j:j+4]):
            ans += 1
        if i + 3 < n and j + 3 < m and check(matri[i][j] + matrix[i+1][j+1] + matrix[i+2][j+2] + matrix[i+3][j+3]):
            ans += 1
print(ans)

当时的结果好像是16520。。。记不太清了


第三题. 跑步

原问题:小明坚持每天跑步,正常情况下每天跑一公里,如果这一天是周一或者月初(每月的一号),那么小明就会跑两公里(如果这一天既是周一,又是月初,小明也是跑两公里),小明从2000年1月1日(周六)一直坚持到了2020年10月1日(周四),请你计算一下小明共跑了多少公里?

解题思路:就是统计2000年1月1日到2020年10月1日(包含)以来共有多少天是周一或者月初,考试的时候绞尽脑汁写得代码,结果还错了,事后看别人题解才知道还有datetime库这个东西,我哭了。

参考代码(事后诸葛亮):

from datetime import *
start = date(2000,1,1)
end = date(2020,10,2)
tmp = timedelta(days = 1)
ans = 0
while start != end:
    if start.weekday() == 0 or start.day == 1:
        ans += 2
    else:
        ans += 1
    start = start + tmp
print(ans)

运行结果为8879


第四题. 蛇形排列 

问题分析:在蛇形排列矩阵中,第20行第20列的数字是多少?蛇形排列方式如图所示:

第十一届蓝桥杯软件类Python组(最新)(试题回忆+部分个人解答)_第1张图片 蛇形排列

 

解题思路:在该数字的左上方有 19+19 = 38 个斜排,最后一个数是 38 * (38+1) / 2 = 741,741 + 20 = 761,如图所示:

第十一届蓝桥杯软件类Python组(最新)(试题回忆+部分个人解答)_第2张图片

如果非得编程求解的话:那就定义两种遍历模式,一种是有↗方向,一种是↙方向,判断行号加上列号的和是单数还是偶数,

参考代码:

i = 0
j = 0
num = 0
while True:
    num += 1
    if i == 19 and j == 19:
        break
    if (i+j)&1:
        i += 1
        if j > 0:
            j -= 1
    else:
        j += 1
        if i > 0:
            i -= 1
print(num)
    

运行结果是761


第五题. 冒泡排序

原问题:对一个字符串,对它进行冒泡排序使其为升序,例如:对于lan,排序成 aln 需要交换一次(只能交换相邻的两个字母),对于qiao,排序成 aioq 就需要交换4次。请找出冒泡排序时恰好需要交换100次的字符串,如果有多个字符串满足条件,则找出最短的那个,如果有多个满足条件而且还是最短的,则找出字典序最小的那个。

问题分析:长度为 n 的降序数组的冒泡排序交换次数是 (n-1) * n / 2 次,大于等于100的第一个数是 105 = (15-1) * 15 / 2,所以最短的长度肯定是15了,再考虑到字典序最小,则答案应该就是onmlkjihgfedcba排列而成的,字典序最小,就需要第一个字母的字典序尽可能小,然后才是第二个、第三个……,那么就把正数第六个字母提到前面,结果应该就是jonmlkihgfedcba(当时推出来以后没有拿程序验证一下 ,心里还是很没底的)

参考验证代码:

def bubble_sort(arr):
    num = 0
    for i in range(len(arr)-1,0,-1):
        for j in range(i):
            if arr[j] > arr[j+1]:
                num += 1
                arr[j],arr[j+1] = arr[j+1],arr[j]
    return num
print(bubble_sort(list('jonmlkihgfedcba')))

运行结果是100


第六题到第十题就是编程题了,第六题第七题很基础,第八题开始就有难度了,

第六题. 成绩统计

问题:给定 n 个学生的成绩,大于等于60的为及格,大于等于85的为优秀。请你统计这 n 名同学的及格率和优秀率。

输入格式:第一行一个数n,表示接下来有n行数据,接下来n行每行一个数m,代表该学生的成绩。

输出格式:两行,第一行一个数表示及格率,第二行一个数表示优秀率,都要求四舍五入。

问题分析:该怎么算就不解释了哈,有点说道的地方就是后面的四舍五入和格式化输出了。

参考代码:

n = int(input())
num1 = 0
num2 = 0
for _ in range(n):
    score = int(input())
    if score >= 60:
        num1 += 1
    if score >= 85:
        num2 += 1
print(str(round(num1*100/n))+'%')
print(str(round(num2*100/n))+'%')

 


第七题. 单词分析

原问题:在给定的字符串中,计算出现次数最多的字母和它的出现次数,如果出现次数最多的字母同时有多个,则找出字典序最小的。

输入格式:一行,代表所要统计的字符串

输出格式:两行,第一行一个字符,是出现最多的字母,第二行一个整数,该字母的出现次数。

解题思路:开一个哈希表统计出现次数就好了。然后从前开始遍历来保证找出的字母的字典序是最小的。

参考代码:

cnt = [0]*26
s = input()
for alpha in s:
    cnt[ord(alpha) - ord('a')] += 1
k = 0
for i in range(26):
    if cnt[i] > cnt[k]:
        k = i
print(chr(k+ord('a')))
print(cnt[k])

第八题. 数字三角形

原问题:在如下图所示的数字三角形中,我们需要从三角形顶部走到底部,在每一个数字处,我们可以选择向临近的右下或者临近的左下走,所经过的数字的总和称为路径和,请你计算从顶部到底部所有路线中最大的路径和为多少?同时要求这条路径选左下的次数和选右下的次数相差不能大于1。

第十一届蓝桥杯软件类Python组(最新)(试题回忆+部分个人解答)_第3张图片 数字三角形

输入格式:第一行一个整数 n ,代表数字三角形的阶数,接下来 n 行中,第 j 行有 j 个整数,代表数字三角形中的第 j 层,整数之间用空格分割。

输出格式:一个整数,代表最大的路径和。

输入样例:

6

1

2 3

7 5 6

4 3 2 3

5 6 5 7 4

7 8 9 6 10 9

输出样例:

29

解题思路:是一个比较原型的动态规划问题,一层一层向下,注意最后输出时要选最后一行的中间两个或者一个。规划过程如下图所示:

第十一届蓝桥杯软件类Python组(最新)(试题回忆+部分个人解答)_第4张图片 规划过程
第十一届蓝桥杯软件类Python组(最新)(试题回忆+部分个人解答)_第5张图片 路径和

参考代码:

n = int(input())
matrix = [[0]*( _ + 1 ) for _ in range(n)]
for i in range(n):
    tmp = [int(a) for a in input().split(' ')]
    matrix[i] = tmp
dp = matrix[:]
for i in range(1,n):
    for j in range(i+1):
        if j == 0:
            dp[i][j] += dp[i-1][j]
        elif j == i:
            dp[i][j] += dp[i-1][j-1]
        else:
            dp[i][j] += max(dp[i-1][j],dp[i-1][j-1])
if n&1:
    print(dp[n-1][n//2])
else:
    print(max(dp[n-1][n//2-1],dp[n-1][n//2]))

第九题. 平面划分

问题:给出N条直线的斜率和截距,计算这些直线会将xy平面划分为多少个区域。

第十一届蓝桥杯软件类Python组(最新)(试题回忆+部分个人解答)_第6张图片

如图中所示,这些直线将平面划分为了7个区域。

输入格式:第一行一个数 n 代表直线的个数,接下来 n 行每行两个整数,分别代表斜率和截距。

输出格式:一行一个整数,代表划分区域的个数。

输入样例:

3

1 1

2 2

3 3

输出样例:

6

解题思路:把这些直线一条一条的加入平面来进行分析,计算当前新加入的直线与之前已加入的直线集合会产生多少个交点,如果产生了k个交点,则划分的区域就会增加 k+1 个(见图所示),在计算交点的时候,需要去重,k个交点的去重时间复杂度大致为O(k*logk),共有N条直线,所以整体时间复杂度为O(N*N*logN),(题目中给出N最大为1000,只能保佑不超时了

第十一届蓝桥杯软件类Python组(最新)(试题回忆+部分个人解答)_第7张图片

参考代码:

n = int(input())
line = []
for _ in range(n):
    tmp = [int(a) for a in input().split(' ')]
    line.append(tuple(tmp))
line = list(set(line)) #去重
n = len(line)
judge = lambda pos1,pos2 : abs(pos1[0] - pos2[0]) + abs(pos1[1] - pos2[1]) < 1e-12  #判断两个点是否为同一个点
ans = 2
for i in range(1,n):
    k1,b1 = line[i]
    sec = []
    for j in range(i):
        k2,b2 = line[j]
        if k2 == k1: continue
        pos_x = (b2-b1)/(k1-k2); pos_y = k1*pos_x + b1  #计算交点的坐标
        sec.append((pos_x,pos_y))
    m = len(sec)
    tmpans = m+1
    #交点的数量小于等于1
    if m < 2:
        ans += tmpans
        continue
    #交点的数量大于等于2,需要去重处理
    sec = sorted(sec,key=lambda x:x[0]) #对交点集合按x轴进行排列
    for i in range(1,m):
        if judge(sec[i-1],sec[i]):
            tmpans -= 1  #有重复的,产生的区域数就减一
    ans += tmpans
print(ans)
    
        

第十题. (标题忘了)

(以下题干是我根据自己的理解写的,官方的题干一堆变量名,当时看了有15分钟才明白是啥意思)

问题:在怪物猎人游戏中,玩家可以通过在装备上镶嵌宝珠来获得收益,一共有六件装备,每件装备上都有一定数量的镶嵌孔,每个镶嵌孔都有各自的等级,而宝珠也有等级,镶嵌孔只能镶嵌比自己等级低的宝珠。关于宝珠的说明,宝珠有系列划分,同系列的宝珠没有区别,每个系列的宝珠镶嵌到一定数量时,都会获得一定的收益,如下面举例:

A系宝珠等级是1级,镶嵌数量是 1,2,3,4,5 时,获得的收益分别是 1,2,3,6,7。镶嵌数量超过5个时,收益仍然为7,镶嵌数量上限为5。

B系宝珠等级是2级,镶嵌数量是 1,2,3,4 时,获得的收益分别是 2,5,8,15。镶嵌数量超过4个时,收益仍然为15。镶嵌数量上限为4,以下同理

C系宝珠等级是2级,镶嵌数量是 1,2,3,4 时,获得的收益分别是 4,7,9,13。

D系宝珠等级是3级,镶嵌数量是 1,2,3,4 时,获得的收益分别是 5,10,14,21。

可以看到,你在每个系列上的收益只与你在这个系列上花费的镶嵌孔数量有关,例如对A系宝珠而言,镶嵌3颗时,单位镶嵌孔收益为3/3 = 1,镶嵌4颗时,单位收益为6/4 = 1.5,镶嵌5颗时,单位收益为7/5 = 1.4。等级越高的宝珠系列 单位收益越高(通常而言是这样),而同等级的宝珠系列(例如B系和C系)的单位收益则显得不相上下。现在需要你找出一套镶嵌方案使总收益最大,只输出这个最大收益值即可。

输入格式:前六行代表装备上的镶嵌孔,每行第一个数代表当前装备的镶嵌孔数量,后面的数依次为镶嵌孔的等级。第七行一个整数n,代表有n个系列宝珠,接下来n行,每行代表一个系列,每行的第一个数代表当前系列宝珠的等级,第二个数代表镶嵌数量上限,接下来几个数从低到高依次代表可达到的收益。

数据限制:镶嵌孔和宝珠的等级L不超过4,每个系列的镶嵌数量上限不超过7,系列的数量不超过10000,镶嵌孔的总数不超过300。

输出格式:一个整数,代表最大收益。

输入样例:

1 1

1 1

2 1 2

2 2 1

1 2

1 3

3

1 5 1 2 3 5 8

2 4 2 5 8 15

3 4 5 10 15 21

输出样例:

20

说明:上例共有4个1级镶嵌孔,3个2级镶嵌孔,1个3级镶嵌孔。A, B, C 三个系列的宝珠,镶嵌方案为

(A)(A)(A)(A)(B)(B)(B)(B)

所以最大总收益为 5+15 = 20

 

解题思路:(我太菜了 想不出来,有时间再更

读题就读了半天,暴力枚举应该可以过前几个测试点,感觉有点像背包问题的意思,比赛快结束的时候码了20分钟才发现思路不对,我还是太菜了,(还不如回去检查一下,这样就能把第二题改过来了)

 

码字不易,如果您觉得有所帮助,麻烦在下面点个赞吧 ~

你可能感兴趣的:(蓝桥杯,算法)