第十六届蓝桥杯大赛软件赛省赛第二场
大家好。最近参加了第十六届蓝桥杯大赛软件赛省赛第二场 Python 大学 B 组的比赛,现在来和大家分享一下我的解题思路和代码实现。以下内容是我自己写的,可能对也可能错,欢迎大家交流讨论。
试题 A:密密摆放
问题描述:小蓝有一个大箱子,内部的长宽高分别是 200、250、240(单位:毫米),他要用这个大箱子来放一些同样大小的小盒子,小盒子的外部长宽高分别是 30、40、50(单位:毫米)。小盒子允许从各个方向旋转(包括可以平放和倒放)。请问小蓝最多可以在一个大箱子里面放多少个小盒子。
解题思路:这道题可以看作是一个空间利用问题。我们需要找到大箱子和小盒子的最优摆放方式,使得小盒子的数量最多。由于小盒子可以旋转,我们可以通过枚举小盒子的摆放方向,计算每种方向下大箱子最多能容纳的小盒子数量,然后取最大值即可。
代码实现:
# 大箱子的长宽高
box = [200, 250, 240]
# 小盒子的长宽高
small_box = [30, 40, 50]# 枚举小盒子的摆放方向
max_count = 0
for i in range(3):for j in range(3):for k in range(3):# 计算每种方向下大箱子最多能容纳的小盒子数量count = (box[0] // small_box[i]) * (box[1] // small_box[j]) * (box[2] // small_box[k])max_count = max(max_count, count)print(max_count)
答案:384
我的答案:5,简直离谱我
试题 B:脉冲强度之和
问题描述:在蓝桥电子工坊,工程师小蓝正在设计一款智能脉冲生成器,用于驱动一种新型设备。该设备的运行依赖于特定的脉冲强度,用正整数 p 表示,其必须满足以下三个条件:
- 可由连续 10 个正整数之和组成:即存在一个正整数 k,使得脉冲强度 p = k + (k + 1) + (k + 2) + · · · + (k + 9)。
- 各个数位上的数字都相同:例如 1111、22222、333333 等。
- 数值不超过 20255202:即 1 ≤ p ≤ 20255202。
通过计算所有符合条件的脉冲强度之和,小蓝能够优化设备运行模式。对此,请帮助他计算这一总和。
解题思路:这道题需要找到所有符合条件的脉冲强度,并将它们相加。我们可以先根据第一个条件,将脉冲强度表示为连续 10 个正整数之和的形式,即 p = 10k + 45。然后,根据第二个条件,枚举各个数位上的数字都相同的数,判断它们是否满足 p = 10k + 45 的形式,且数值不超过 20255202。
代码实现:
# 初始化脉冲强度之和
total_sum = 0# 枚举各个数位上的数字都相同的数
for digit in range(1, 10): # 数字范围为 1 到 9for length in range(1, 8): # 数字长度范围为 1 到 7(因为 20255202 是 8 位数)# 构造各个数位上的数字都相同的数num = int(str(digit) * length)# 判断是否满足 p = 10k + 45 的形式if (num - 45) % 10 == 0 and num <= 20255202:total_sum += numprint(total_sum)
答案:6172835 无语了
试题 C:25 之和
问题描述:小蓝最近对求和很着迷,给定一个正整数 n,他想求从 n 开始的连续 25 个整数的和,即 n + (n + 1) + (n + 2) + · · · + (n + 24),请帮帮他吧。
解题思路:这道题可以直接使用等差数列的求和公式来解决。等差数列的求和公式为:S = (首项 + 末项) × 项数 / 2。在这个问题中,首项为 n,末项为 n + 24,项数为 25。
代码实现:
n = int(input())
print(int(((n + n + 24) * 25) / 2))
试题 D:旗帜
问题描述:小蓝要画一个 LANQIAO 图形,并把这个图形做成一个旗帜。图形的形状为一个 h×w 的矩形,其中 h 表示图形的高,w 表示图形的宽。当 h = 5, w = 10 时,图形如下所示:
LANQIAOLAN
ANQIAOLANQ
NQIAOLANQI
QIAOLANQIA
IAOLANQIAO
图形的规律是:第一行用 LANQIAO 重复填入,第二行开始,每行向左移动一个字符,用 LANQIAO 重复填入。小蓝需要把图形中的每个字母都剪出来,以粘贴到旗帜上,他想知道,给定图形的高和宽,图形中有多少个 A。
解题思路:这道题可以通过模拟图形的生成过程来解决。首先,根据图形的规律,生成每一行的字符串,然后统计每一行中 A 的个数,最后将所有行中 A 的个数相加即可。
代码实现:
h, w = map(int, input().split())
s = "LANQIAO"
res = []
for i in range(h):tmp = ""tmp += s[i % 7:]while len(tmp) < w:tmp += sres.append(tmp[:w])
ans = 0
for i in res:ans += (i.count('A'))
print(ans)
试题 E:消消乐
问题描述:小蓝正在玩一个叫 “一维消消乐” 的游戏。游戏初始时给出一个长度为 n 的字符串 S = S0S1 · · · Sn−1,字符串只包含字符 A 和 B。小蓝可以对这个字符串进行若干次操作,每次操作可以选择两个下标 i, j ∈ [0, n − 1],如果 i < j 且 Si = A 且 Sj = B,小蓝就可以把它们同时消掉。小蓝想知道在经过若干次操作后,直到无法对字符串继续进行操作时,字符串最多剩下多少个字符。
解题思路:这道题可以通过贪心算法来解决。从左到右遍历字符串,找到第一个 A 和最后一个 B,将它们消掉,然后继续寻找下一个 A 和 B,直到无法继续消掉为止。最后剩下的字符数量就是答案。
代码实现:
S = input()
n = len(S)
ans = n
i, j = 0, n - 1
while i < j:while S[i] != 'A' and i < n:i += 1while S[j] != 'B' and j >= 0:j -= 1if i < j and S[i] == 'A' and S[j] == 'B':ans -= 2i += 1j -= 1
print(ans)
试题 F:数列差分
问题描述:小蓝有两个长度均为 n 的数列 A = {a1, a2, · · ·, an} 和 B = {b1, b2, · · ·, bn},将两个数列作差定义为 C = A − B = {c1 = a1 − b1, c2 = a2 − b2, · · ·, cn = an − bn}。小蓝将对数列 B 进行若干次操作,每次操作可以将数列 B 中的任意一个数更改为任意一个整数。在进行完所有操作后,小蓝可以按任意顺序将数列 B 重排,之后再计算数列 C。小蓝想知道,最少操作多少次可以使得数列 C 中的所有数都为正整数。
解题思路:这道题可以通过排序和贪心算法来解决。首先,将数列 A 和 B 按照从小到大的顺序排序。然后,从左到右遍历数列 A 和 B,对于每个位置 i,如果 A[i] - B[i] <= 0,则需要对 B[i] 进行操作,将其更改为一个更小的数,使得 A[i] - B[i] > 0。最后,统计需要操作的次数即可。
代码实现:
n = int(input())
A = list(map(int, input().split()))
B = list(map(int, input().split()))
B.sort(reverse=True)
res = 0
flag = [False] * n
for j in range(n):is_ok = Falsefor i in range(n):if A[j] - B[i] > 0 and not flag[i]:flag[i] = Trueis_ok = Truebreakif not is_ok:res += 1
print(res)
试题 G:树上寻宝
问题描述:小蓝正在一棵含有 n 个结点的树的根结点 1 上,他准备在这棵树上寻宝。结点 i 上有一个物品,价值为 wi。然而,小蓝每次寻宝只能从根节点出发走不超过 k 步,每步只能选择走 1 条边或者 2 条边,之后会自动拾取最终停留的结点上的物品并被传送回根结点。请求出小蓝最终能获得的物品的总价值。
解题思路:这道题可以通过深度优先搜索(DFS)来解决。从根结点出发,使用 DFS 遍历树,记录每个结点的深度。在遍历过程中,如果当前结点的深度不超过 k,则将该结点的物品价值加入总价值中。最后,返回总价值即可。
代码实现:
from collections import defaultdictn,k=map(int,input().split())
# print(n,k)
value=list(map(int,input().split()))
# print(value)
tree=defaultdict(list)
# tree=dict(list)
for i in range(n-1):a,b=map(int,input().split())# print(a,b)tree[a].append(b)# print(tree[a])
# print()
# print(tree)
path=defaultdict(list)#当前的节点索引 i 当前已经走过多少边 j
# now=1
def dfs(i,j):if j>k*2:return path[j].append(i)for w in (tree[i]):dfs(w,j+1)dfs(1,0)
S=set()
for i in range(0,k*2+1):# print(path[i])for x in path[i]:S.add(x)
# print(S)
res=0
# print(value)
for i in S:res+=value[i-1]
print(res)# print(path)'''
7 1
1 1 1 1 1 1 1
1 2
1 3
2 4
2 5
3 6
3 7''''''
8 2
6 3 3 1 5 4 3 4
1 2
2 3
2 4
4 5
5 6
6 7
7 8
'''
试题 H:破解信息
问题描述:在遥远的未来,星际旅行已经成为常态。宇航员小蓝在一次探险任务中,意外发现了一个古老的太空遗迹。遗迹中存放着一个数据存储器,里面记录着一段加密的信息。经过初步分析,小蓝发现这段信息可以被表示为一个字符串 S,而解密的关键,在于找出 S 中字典序最大的回文子序列。
解题思路:这道题可以通过动态规划来解决。首先,定义一个二维数组 dp,其中 dp[i][j] 表示字符串 S 从第 i 个字符到第 j 个字符的最长回文子序列。然后,根据动态规划的状态转移方程,计算 dp 数组的值。最后,从 dp 数组中找到字典序最大的回文子序列即可。
代码实现:
S=input()n=len(S)
i,j=0,n-1
left=[]
right=[]
pre=n-1
path=[]for i in range(n):while i<=j:if i==j:left.append(S[i])right=right[::-1]huiwen=left+rightpath.append(huiwen)breakleft.append(S[i])while S[j]!=left[-1] and i<j:j-=1if S[j]==left[-1] and i<j:right.append(S[j])pre=jj-=1else:left.pop(-1)i=i+1j=prei+=1right=right[::-1]huiwen=left+rightpath.append(huiwen)left=[]right=[]j=n-1ans=[]
for i in path:ch=""for j in i:ch+=jans.append(ch)
ans.append(max(list(S)))print(max(ans))