蓝桥杯2020省赛python

蓝桥杯2020省赛Python

第一题:门牌制作

在这里插入图片描述

用了一个时间复杂度是n的算法,反正是填空题也不会出现TLE的事,只要别太离谱就行了。

利用python 的count函数

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

答案是2

第二题:寻找2020

在这里插入图片描述

就一行一列的找吧,先遍历每一行,再遍历每一列,这样对于第i行,只要j+4 <= 总列数,就可以遍历矩阵的[i][j],[i][j+1]…[i][j+3],看看他是否等于2020

对于列的呢,只要当前的行数 i + 3 < 总行数 就可以更上面的一样遍历,行和列换一下而已

斜着的同样的,只要i + 3 < 总行数,j + 3 < 总列数

PS:j + 3 < 总列数 和j+4 <= 总列数是一样的,只不过第一个的时候下面要用到j+4 我就写j+4了

nums = [[2, 2, 0, 0, 0, 0],
        [0, 0, 0, 0, 0, 0],
        [0, 0, 2, 2, 0, 2],
        [0, 0, 0, 0, 0, 0],
        [0, 0, 0, 0, 2, 2],
        [0, 0, 2, 0, 2, 0],
        ]
res = 0
for i in range(len(nums)):  # 行
    for j in range(len(nums[0])): # 列
        if j + 4 <= len(nums[0]):   # 超出了
            a = nums[i][j:j+4]
            if a == [2,0,2,0]:
                res += 1
        if i+3 < len(nums):
            b = nums[i][j]*1000 + nums[i+1][j] * 100 + nums[i+2][j] *10 + nums[i+3][j] 
            if b == 2020:
                res += 1
        if i+3 < len(nums) and j+3 < len(nums[0]):
            c = nums[i][j] * 1000 + nums[i+1][j+1] * 100 +nums[i+2][j+2] * 10 + nums[i+3][j+3]
            if c ==2020:
                res += 1
print(res)

第三题:跑步锻炼

在这里插入图片描述

就判断呗,如果是周一或者月初,就 + 2 ,否则就加1,这里不用特殊考虑同时的情况,因为我们如果是周一的话或者月初的话都会直接continue,只会加一次2,python有专门的datetime库可以做这道题

import datetime
a = datetime.date(2000,1,1)
b = datetime.date(2020,10,2)

res = 0
while True:
    if a == b: break

    if a.day == 1:
        res += 2
        a = a + datetime.timedelta(days = 1)
        continue
    if a.isoweekday() == 1:
        res += 2
        a = a+datetime.timedelta(days = 1)
        continue
    res += 1
    a = a + datetime.timedelta(days = 1)

print(res)

4.蛇形填数

在这里插入图片描述

就填呗,如果i是偶数,就j从0到i-1 顺着填,否则就反过来

lst = [[] for _ in range(40)]
lst[0].append(1)
num=1
for i in range(2,40):
    if i % 2 == 0:
        for j in range(i):
            num += 1
            lst[j].append(num)
    else:
        for j in range(i):
            num += 1
            lst[i - j -1].append(num)
for i in range(len(lst)):
    print(i + 1, lst[i])
print(lst[19][19])

PS 我看了一下,直接找规律我估计也行

5.排序

在这里插入图片描述

这就需要了解一下冒泡排序的原理了,首先如果n个数全都倒着排的话,一共有 n-1 + n-2 + n-3 … + 1次要交换顺序

又因为他要最短的英文顺序,所以我们就先按逆序排,当有15个英文字母全都逆序的时候,总共要交换105次。又要字典序小,那就是o…a了。

接着又因为字典序小,所以我们尽量把小的往第一个放,同时满足交换100次,那就把j放到前面,这样前面五个单词就少跟j交换一次了,所以答案是

print('jonmlkihgfedcba')

第六题:成绩统计

在这里插入图片描述

这题就比较简单就不多说明了

if __name__ == '__main__':
    n = int(input())
    jige = 0
    youxiu = 0
    for i in range(n):
        m = int(input())
        if m >= 85:
            youxiu += 1
            jige += 1
        elif m >= 60:
            jige += 1

    print('{:.0f}%'.format((jige/n)*100)) 
    print('{:.0f}%'.format((youxiu/n)*100)) 

第七题:单词分析

在这里插入图片描述

最开始我感觉应该用count函数来做,但后面想想又要排字典序是有点麻烦的,我们就把他放到collections来做,里面的defaultdict(int)就可以用来计数,然后转化成字典

import collections
s = input()
dic = collections.defaultdict(int)  # 参数输int就可以计数
for i in s:
    dic[i] += 1
dic = dict(dic.items())
dic = sorted(dic.items(),key= lambda x:x[0], reverse=False)  # 先按字典序排 升序,排完就变成一个列表了
dic = sorted(dic, key = lambda x:x[1],reverse=True)          # 再按大小排,这样就都排好了 降序
print(dic[0][0])
print(dic[0][1])

第八题:数字三角形

在这里插入图片描述

最开始我看的时候我还以为是最基本的数字三角形,写完发现答案不对,我的是30,他是27,又看了遍题目发现他要求向左和向右次数之差不能超过1.

然后我又愚蠢的去写了一个,到达每一个顶点的向左向右的次数都不能超过1,发现还是不对,因为这样就限制了整体。他只要求到最后一行的时候,路径向左和向右的次数相差不能超过1

最后推了一遍,如果n是奇数,那么要到最后一行并且路径向左向右次数不能超过1的话,他只能到达中间那个。如果n是偶数,那么他只能到达中间两个(这个方法是过的了我去试了证明没问题)

# 如果符合要求的话 n 为奇数只有最后一行的中间点符合 偶数只有中间两个点符合
if __name__ == '__main__':
    n = int(input())
    f,a  = [[-1]*(n+1) for _ in range(n+1)],[[0] for _ in range(N)]
    

    for i in range(1,n+1):
        a[i] += [int(x) for x in input().split()]
    
    f[1][1] = a[1][1]
    for i in range(2,n+1): # 第i行
        for j in range(1,i+1):  # 第j列
            f[i][j] = max(f[i-1][j] + a[i][j], f[i-1][j-1] + a[i][j])

    if n % 2 == 0:
        res = max(f[n][n//2],f[n][n//2+1])
    else:
        res = f[n][n//2+1]

    print(res)

第九题:平面切分

在这里插入图片描述

这道题因为我之前pythontip 上面刷过,所以做起来不会感觉很难,就是找规律,如果后面加进来的线和前面的线有n个不同的交点,那么他就会多加n+1个平面

n = int(input())
lines = []
for i in range(n):
    a, b = map(int, input().split())
    lines.append((a, b))
lines = list(set(lines))  # 去重
def cross(line1,line2):  # 求交点
    A1,B1,A2,B2 = line1[0],line1[1],line2[0],line2[1]
    if A1 - A2 == 0: return # 返回NONE
    x = (B2 - B1) / (A1 - A2)
    y = A1 * x + B1
    x = round(x, 10)
    y = round(y, 10)
    return (x, y)
ci = [1] *(n+1)  # 第i条直接加入对答案的贡献,下标从0开始,默认那个1就已经加上了
node = set()
for i in range(1,n): # 从第二条线开始
    node.clear()
    for j in range(i):
        tmp = cross(lines[i],lines[j])
        if tmp == None: continue
        node.add(tmp)
    ci[i] += len(node)
print(sum(ci[:n])+1)   # 加上最开始其实是有两个平面,我们只算了一个

第十题:装饰珠

在这里插入图片描述

扫描二维码关注公众号,回复: 16520921 查看本文章

嗯最后一道题还是很有趣的,对于这种题我一般来说是只要能做出来就好,不考虑TLE。。所以我用了一种算是暴力的做法。

其实他并不在意六件装备是怎么样的,他只在意总共的孔数和等级以及所有珠子的等级和他的价值,那么我们先把所有装备的孔数和等级存储起来,

lv[i] 表示等级为i的物品的个数

limit[i]表示等级为i的珠子最后能放多少个

value[i][j]表示等级为i的珠子放了j个的价值

lv = [0]*5  # 表示等级为i的孔的数量
limit = [0]*5
value = [[0] for i in range(5)]
for i in range(6):
    a = list(map(int,input().split()))
    for i in range(1,len(a)):
        lv[a[i]] += 1  #等级为i的物品+1 
        m = int(input())
for i in range(m):
    zhu = list(map(int,input().split()))
    limit[zhu[0]] = zhu[1]              # limit[i] 表示等级为i的珠子最多镶嵌多少个
    value[zhu[0]] += zhu[2:]             # value[i][j] 表示等级为i的珠子用了j个的价值

好了现在都存好了,我们就开始遍历所有的可能性,

就遍历等级为4的珠子放i个 ,为3的珠子放j个,要注意的是,等级为4的珠子最多能放min(limit[4],lv[4])个,也就是不能超过等级4的珠子的限制和等级为4的装备的孔数量,等级为3的同理,只不过他可以放在等级为4和等级为3的装备孔中。

res = 0
# 对每个珠子的等级进行枚举
for i in range(min(lv[4],limit[4])+1):  # 等级为4的选i个
    for j in range(min(lv[3] + lv[4] - i,limit[3])+1):  # 等级为3的珠子能放进3和4的孔中
        for k in range(min(lv[4] + lv[3] + lv[2] -i -j,limit[2])+1):
            for l in range(min(lv[4] + lv[3] + lv[2] + lv[1] -i -j -k,limit[1])+1):
                res = max(res,value[4][i] + value[3][j] + value[2][k] + value[1][l])
        

print(res) 

完整代码如下

lv = [0]*5  # 表示等级为i的孔的数量
limit = [0]*5
value = [[0] for i in range(5)]
# print(summ)
for i in range(6):
    a = list(map(int,input().split()))
    for i in range(1,len(a)):
        lv[a[i]] += 1  #等级为i的物品+1 

m = int(input())
for i in range(m):
    zhu = list(map(int,input().split()))
    limit[zhu[0]] = zhu[1]              # limit[i] 表示等级为i的珠子最多镶嵌多少个
    value[zhu[0]] += zhu[2:]             # value[i][j] 表示等级为i的珠子用了j个的价值
res = 0
# 对每个珠子的等级进行枚举
for i in range(min(lv[4],limit[4])+1):  # 等级为4的选i个
    for j in range(min(lv[3] + lv[4] - i,limit[3])+1):  # 等级为3的珠子能放进3和4的孔中
        for k in range(min(lv[4] + lv[3] + lv[2] -i -j,limit[2])+1):
            for l in range(min(lv[4] + lv[3] + lv[2] + lv[1] -i -j -k,limit[1])+1):
                res = max(res,value[4][i] + value[3][j] + value[2][k] + value[1][l])
        

print(res)

猜你喜欢

转载自blog.csdn.net/abc1234564546/article/details/128758682