问题 A: 菱形图案
题目描述
KiKi学习了循环,BoBo老师给他出了一系列打印图案的练习,该任务是打印用“*”组成的菱形图案。
输入
多组输入,一个整数(2~20)。
输出
针对每行输入,输出用“*”组成的菱形,每个“*”后面有一个空格。每输出一个菱形的后面需要空一行。
样例输入 Copy
2 3 4
样例输出 Copy
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
while True:
n = int(input())
for i in range(n):
print(' ' * (n - i) + '* ' * (i + 1))
print('* ' * (n+1))
for i in range(n):
print(' ' * (i + 1) + '* ' * (n - i))
print()
问题 B: X星人的礼物
题目描述
六一儿童节到了,X星人宝宝收到了很多很多礼物。他决定把这些礼物装到自己的礼物箱中。为此,他准备了很多个型号相同的礼物箱,每个礼物箱能够装礼物的最大重量都是一样的。但是X星人宝宝不希望在一个礼物箱里面装太多礼物(可能担心礼物会被压坏吧),每个礼物箱最多只允许装2个礼物。
假设X星人宝宝收到了N个礼物,现在给出每一个礼物的重量和一个礼物箱的最大装载量,请你编写一个程序计算X星人宝宝最少要用多少个礼物箱才能够把所有的礼物都装完。
输入
单组输入。
每组两行,第1行输入两个正整数,分别表示礼物的数量N和每个礼物箱的最大装载量C,其中1<=N<=1000,1<=C<=100,两者之间用英文空格隔开。
第2行输入N个不超过100的正整数,分别表示每一个礼物的重量,两两之间用英文空格隔开。
输入保证最重的礼物的重量<=C。
输出
针对所输出的数据,输出将所有的礼物全部都装完所需的礼物箱的最少个数。
样例输入 Copy
5 80 20 70 40 30 10
样例输出 Copy
3
def count_pairs(arr, c):
arr.sort()
count = 0
left = 0
right = len(arr) - 1
# 遍历数组
while left < right:
if arr[left] + arr[right] <= c:
left += 1
right -= 1
count += 1
if left == right and left < len(arr):
count += 1
return count
while True:
n, c = map(int, input().split())
arr = list(map(int, input().split()))
print(count_pairs(arr, c))
问题 C: 隔离14天
题目描述
题目涉政
输入
输出
样例输入 Copy
100 4 2 1 2 5 10 13 11 12 14 2 0 1 2 99 2
样例输出 Copy
4
n, m = map(int, input().split())
a = [] # 存储每辆车的乘客列表
p = [] # 存储已经检查过的车辆索引
q = [] # 存储所有阳性乘客的列表
for i in range(m):
a.append(list(map(int, input().split()))[1:])
for i in range(m):
if 0 in a[i]:
p.append(i)
q.extend(a[i])
q = list(set(q))
found_new = True
while found_new:
found_new = False
for i in range(m):
if i not in p:
if any(passenger in q for passenger in a[i]):
p.append(i)
q.extend(a[i])
found_new = True
break
unique_q = set(q)
print(len(unique_q))
问题 D: 最小生成树(Kruskal)
题目描述
编程实现Kruskal算法,求图的最小生成树(MST)的权重。
输入
每组数据分为两个部分,第一部分为图的点数n,和边数m,
第二部分为m行,每一行输入三个数字,前两个为两个顶点的编号,第三个为边权重。
输出
最小生成树的权重。
样例输入 Copy
3 3 0 1 10 0 2 15 1 2 50
样例输出 Copy
25
class UnionFind:
def __init__(self, n):
self.parent = list(range(n))
self.rank = [0] * n
def find(self, x):
if self.parent[x] != x:
self.parent[x] = self.find(self.parent[x])
return self.parent[x]
def union(self, x, y):
rootX = self.find(x)
rootY = self.find(y)
if rootX != rootY:
if self.rank[rootX] > self.rank[rootY]:
self.parent[rootY] = rootX
elif self.rank[rootX] < self.rank[rootY]:
self.parent[rootX] = rootY
else:
self.parent[rootY] = rootX
self.rank[rootX] += 1
def kruskal(n, edges):
edges.sort(key=lambda x: x[2])
uf = UnionFind(n)
total_weight = 0
mst_edges = 0
for edge in edges:
u, v, weight = edge
if uf.find(u) != uf.find(v):
uf.union(u, v)
total_weight += weight
mst_edges += 1
if mst_edges == n - 1: # 当MST包含n-1条边时,停止添加边
break
return total_weight
n, m = map(int, input().split())
edges = []
for _ in range(m):
u, v, weight = map(int, input().split())
edges.append((u, v, weight))
print(kruskal(n, edges))
问题 E: 搭建电路
题目描述
明明迷上了一个搭建电路的游戏。
在游戏中,每次在两个电子元件之间增加一条有效电路(两个元件之间先前没有电路相连)都将获得相应的积分奖励。
已知电子元件数量n和部分电子元件之间的奖励积分值。如何构建一个有效电路将所有元件全部连接起来,并且可以得到最多的积分奖励。
输入
每组输入数据包含m+1行。
第1行输入两个正整数n和m,其中n表示电子元件数量(n<=100),m表示提供了m对电子元件之间的奖励积分值(m<=1000)。两个正整数之间用空格隔开。
第2行到第m+1行对应m对电子元件及其对应的奖励积分值,每一行包含三个正整数,第1个和第2个整数表示电子元件编号(从1开始),第3个整数表示两个元件之间搭建电路的奖励积分num(num<1e9)。整数之间用空格隔开。
输出
每组输出占1行,输出一个正整数,即最多可以得到的积分奖励值。如果没有办法把所有元件全部连接起来,则输出“No solution.”。
样例输入 Copy
3 3 1 2 10 1 3 20 2 3 30
样例输出 Copy
50
class UnionFind:
def __init__(self, n):
self.parent = list(range(n))
self.rank = [0] * n
def find(self, x):
if self.parent[x] != x:
self.parent[x] = self.find(self.parent[x])
return self.parent[x]
def union(self, x, y):
rootX = self.find(x)
rootY = self.find(y)
if rootX != rootY:
if self.rank[rootX] > self.rank[rootY]:
self.parent[rootY] = rootX
elif self.rank[rootX] < self.rank[rootY]:
self.parent[rootX] = rootY
else:
self.parent[rootY] = rootX
self.rank[rootX] += 1
def max_score_mst(n, edges):
if n == 1:
return 0
uf = UnionFind(n)
edges.sort(key=lambda x: x[2], reverse=True)
total_score = 0
for u, v, score in edges:
if uf.find(u - 1) != uf.find(v - 1):
uf.union(u - 1, v - 1)
total_score += score
if len({uf.find(i) for i in range(n)}) == 1:
return total_score
else:
return "No solution."
while 1:
n, m = map(int, input().split())
edges = []
for _ in range(m):
u, v, score = map(int, input().split())
edges.append((u, v, score))
print(max_score_mst(n, edges))
问题 F: 最小生成树(Prim)
题目描述
使用Prim算法求图的最小生成树(MST)
输入
每组数据分为两个部分,第一部分为图的点数n,和边数m,
第二部分为m行,每一行输入三个数字,前两个为两个顶点的编号,第三个为边权重。
输出
最小生成树,输出时按照边的两个端点的升序输出。(先看左端点,再看右端点,端点不换位置)
样例输入 Copy
3 3 0 1 10 0 2 15 1 2 50
样例输出 Copy
0 1 10 0 2 15
def judge(a, b, c, vis):
# 判断边(a, b)是否连接了两个不同树的顶点
return a not in vis and b not in vis
def find(x, parent):
# 路径压缩
if parent[x] != x:
parent[x] = find(parent[x], parent)
return parent[x]
def union(x, y, parent):
# 合并两个顶点所在的树
rootX = find(x, parent)
rootY = find(y, parent)
if rootX != rootY:
parent[rootY] = rootX
def kruskal(n, m, arr):
parent = list(range(n)) # 并查集的父节点数组
res = []
cnt = 0 # 已加入MST的边的数量
# 按权重对边进行排序
arr.sort(key=lambda x: x[2])
for a, b, c in arr:
if cnt == n - 1: # 如果已经找到n-1条边,退出循环
break
if judge(a, b, c, set(res)): # 判断是否连接两个不同的树
rootA = find(a, parent)
rootB = find(b, parent)
if rootA != rootB: # 如果a和b不在同一个树中
union(rootA, rootB, parent) # 合并两个树
res.append((a, b, c)) # 添加到结果中
cnt += 1
res.sort(key=lambda x: (x[0], x[1]))
return res
n, m = map(int, input().split())
arr = []
for _ in range(m):
arr.append(list(map(int, input().split())))
mst = kruskal(n, m, arr)
for edge in mst:
print(*edge)