算法应用主题赛 · Python · 共 14 题(5单选+5多选+4编程)· 满分 100 分
[45, 12, 78, 33, 56]进行冒泡排序(升序),第一轮冒泡结束后的序列是?题目描述:
蒙古族牧民在草原上游牧,草原可以看作一个m行n列的网格。网格中每个位置可能是:
- 0 表示草地(可以通过)
- 1 表示戈壁或山地(不可通过)
牧民从起点位置(start_x, start_y)出发,需要到达终点位置(end_x, end_y)。牧民每次只能向上下左右四个方向之一移动一格,且不能移动到网格外或戈壁/山地上。
请编写程序,计算从起点到终点的最短步数。如果无法到达终点,输出-1。
注意:行列索引均从0开始计数。
输入格式:
第一行输入两个整数m和n,表示网格的行数和列数,用空格分隔(1 ≤ m, n ≤ 100)。
接下来m行,每行输入n个整数(0或1),表示网格地图。
最后一行输入四个整数start_x, start_y, end_x, end_y,分别表示起点和终点的行列坐标,用空格分隔。
输出格式:
输出一个整数,表示从起点到终点的最短步数。若无法到达则输出-1。
示例输入:
示例输出:
from collections import deque
m, n = map(int, input().split())
grid = []
for _ in range(m):
grid.append(list(map(int, input().split())))
start_x, start_y, end_x, end_y = map(int, input().split())
# 如果起点或终点本身是障碍,无法到达
if grid[start_x][start_y] == 1 or grid[end_x][end_y] == 1:
print(-1)
else:
# BFS
# 四个方向:上、下、左、右
dx = [-1, 1, 0, 0]
dy = [0, 0, -1, 1]
# visited数组记录是否访问过
visited = [[False] * n for _ in range(m)]
visited[start_x][start_y] = True
# 队列中存储 (x, y, 步数)
queue = deque()
queue.append((start_x, start_y, 0))
answer = -1
while queue:
x, y, steps = queue.popleft()
# 到达终点
if x == end_x and y == end_y:
answer = steps
break
# 向四个方向扩展
for k in range(4):
nx = x + dx[k]
ny = y + dy[k]
# 检查边界、是否可通行、是否已访问
if 0 <= nx < m and 0 <= ny < n:
if grid[nx][ny] == 0 and not visited[nx][ny]:
visited[nx][ny] = True
queue.append((nx, ny, steps + 1))
print(answer)
题目描述:
傣族泼水节上有n个水池,每个水池有一个容量c_i(单位:升)和一个单位快乐值h_i。每向第i个水池加入1升水,就能获得h_i点快乐值,但加入的水量不能超过该水池的容量c_i。现在总共有M升水可以分配。
请使用贪心策略(优先向单位快乐值最高的水池加水;若单位快乐值相同,优先向容量大的水池加水),计算能获得的最大总快乐值。
输入格式:
第一行输入两个整数n和M,表示水池数量和总水量,用空格分隔(1 ≤ n ≤ 100,1 ≤ M ≤ 10000)。
接下来n行,每行输入两个整数c_i和h_i,分别表示第i个水池的容量和单位快乐值(1 ≤ c_i ≤ 1000,1 ≤ h_i ≤ 100)。
输出格式:
第一行输出一个整数,表示最大总快乐值。
接下来若干行,每行输出一个水池的分配信息:"水池i: 加入X升",按加水顺序输出。若某个水池没有被分配到水,则不输出。
示例输入:
示例输出:
n, M = map(int, input().split())
pools = []
for i in range(n):
c, h = map(int, input().split())
pools.append([i + 1, c, h])
# 按单位快乐值降序排序;单位快乐值相同按容量降序
pools.sort(key=lambda x: (-x[2], -x[1]))
remaining = M
total_joy = 0
results = []
for idx, cap, joy in pools:
if remaining <= 0:
break
if cap <= remaining:
# 加满该水池
results.append((idx, cap))
total_joy += cap * joy
remaining -= cap
else:
# 只能加入部分水
results.append((idx, remaining))
total_joy += remaining * joy
remaining = 0
print(total_joy)
for idx, amount in results:
print(f"水池{idx}: 加入{amount}升")
题目描述:
苗族银匠有一批精美的银饰,每件银饰有其重量w_i(克)和艺术价值v_i。银匠准备将这些银饰装入展示箱,展示箱的最大承重为W(克),总重量不能超过W。每件银饰只能选择装入或不装入(不可分割)。
请编写程序,使用0-1背包动态规划算法,计算在不超过最大承重的前提下,能够获得的最大总艺术价值。
输入格式:
第一行输入两个整数n和W,表示银饰数量和展示箱最大承重,用空格分隔(1 ≤ n ≤ 100,1 ≤ W ≤ 1000)。
接下来n行,每行输入两个整数w_i和v_i,表示第i件银饰的重量和艺术价值(1 ≤ w_i ≤ 200,1 ≤ v_i ≤ 1000)。
输出格式:
第一行输出一个整数,表示最大总艺术价值。
第二行输出被选中的银饰编号(从1开始),按编号升序排列,用空格分隔。若有多组最优解,输出其中任意一组即可。
示例输入:
示例输出:
n, W = map(int, input().split())
weights = [0]
values = [0]
for i in range(1, n + 1):
w, v = map(int, input().split())
weights.append(w)
values.append(v)
# dp[i][j]: 考虑前i件银饰,总重量不超过j时的最大价值
dp = [[0] * (W + 1) for _ in range(n + 1)]
# 记录选择路径:choice[i][j] 表示在考虑前i件、容量为j时是否选择了第i件
choice = [[False] * (W + 1) for _ in range(n + 1)]
for i in range(1, n + 1):
for j in range(1, W + 1):
# 不选第i件
dp[i][j] = dp[i - 1][j]
# 可以选第i件
if j >= weights[i]:
if dp[i - 1][j - weights[i]] + values[i] > dp[i][j]:
dp[i][j] = dp[i - 1][j - weights[i]] + values[i]
choice[i][j] = True
print(dp[n][W])
# 回溯找出被选中的银饰编号
selected = []
j = W
for i in range(n, 0, -1):
if choice[i][j]:
selected.append(i)
j -= weights[i]
selected.sort()
print(' '.join(map(str, selected)))
题目描述:
藏族唐卡画师在一块m行n列的画布上绘制图案。画布上的每个格子用数字表示颜色(相同的数字代表同一种颜色,0表示未上色区域,不计入连通区域)。如果两个同色格子上下左右相邻(四连通),则它们属于同一个连通颜色区域。
请编写程序,使用深度优先搜索(DFS)或广度优先搜索(BFS),统计画布中一共有多少个连通颜色区域(值为0的格子不算颜色区域)。
输入格式:
第一行输入两个整数m和n,表示画布的行数和列数,用空格分隔(1 ≤ m, n ≤ 100)。
接下来m行,每行输入n个整数(非负整数,范围0~9),表示每个格子的颜色值。
输出格式:
第一行输出一个整数,表示连通颜色区域的总数。
接下来每行输出一个连通区域的信息:颜色值和该颜色连通区域的格子数,格式为"颜色X: Y个格子"。按颜色值从小到大的顺序输出;同一颜色可能有多个连通区域,每个独立区域单独计算。
示例输入:
示例输出:
import sys
sys.setrecursionlimit(1000000)
m, n = map(int, input().split())
grid = []
for _ in range(m):
grid.append(list(map(int, input().split())))
visited = [[False] * n for _ in range(m)]
# 四个方向:上、下、左、右
dx = [-1, 1, 0, 0]
dy = [0, 0, -1, 1]
def dfs(x, y, color):
"""从(x,y)出发DFS搜索同色连通区域,返回该区域的格子数"""
count = 1
visited[x][y] = True
for k in range(4):
nx = x + dx[k]
ny = y + dy[k]
if 0 <= nx < m and 0 <= ny < n:
if not visited[nx][ny] and grid[nx][ny] == color:
count += dfs(nx, ny, color)
return count
# BFS版本(备选)
from collections import deque
def bfs(start_x, start_y, color):
"""从(start_x, start_y)出发BFS搜索同色连通区域,返回该区域的格子数"""
count = 0
queue = deque()
queue.append((start_x, start_y))
visited[start_x][start_y] = True
while queue:
x, y = queue.popleft()
count += 1
for k in range(4):
nx = x + dx[k]
ny = y + dy[k]
if 0 <= nx < m and 0 <= ny < n:
if not visited[nx][ny] and grid[nx][ny] == color:
visited[nx][ny] = True
queue.append((nx, ny))
return count
# 遍历整个画布,找出所有连通区域
regions = [] # 存储 (颜色, 格子数)
for i in range(m):
for j in range(n):
if grid[i][j] != 0 and not visited[i][j]:
# 使用DFS
# region_size = dfs(i, j, grid[i][j])
# 或使用BFS(任选一种,效果相同)
region_size = bfs(i, j, grid[i][j])
regions.append((grid[i][j], region_size))
# 先按颜色值排序,相同颜色按发现的先后顺序(即原始顺序)
regions.sort(key=lambda x: x[0])
print(len(regions))
for color, size in regions:
print(f"颜色{color}: {size}个格子")