核心总结
社交网络消息传播 、成绩/绩效统计分析 两类题目为偏易,前者仅需掌握BFS图遍历的基础应用(队列操作、邻接表构建),后者聚焦简单的遍历统计与条件筛选,核心逻辑直观,无复杂算法推导;
字符串编辑距离与相似度 、改进型移位加密 属于中等偏易,前者需理解动态规划的状态转移逻辑并通过滚动数组优化空间,后者需精准处理ASCII码运算与字符循环移位规则,难点在于算法细节的精准实现而非核心逻辑设计;
矩阵路径搜索 难度达到中等,尽管核心是BFS/DFS基础搜索,但需同时兼顾路径回溯、重复节点规避,且步长越界、步长为0等边界场景判断,以及不同输入格式的解析,增加了逻辑复杂度,是入门到进阶的过渡类题目;
整体无中等偏上及以上难度题目,核心难点集中在算法细节落地、边界场景处理与输入输出格式的严格适配,而非多算法融合或大数据量优化,适配算法入门阶段学习者巩固基础并接触简单进阶逻辑。
文章目录
A类-社交网络消息传播问题
相似题目差异总结:
- 核心差异:输入中关注关系的表示方式不同(A1为u→v直接表示传播方向,A2为u v表示v关注u即传播方向u→v),输出要求不同(A1需输出每个用户的可达状态、最短距离及路径,A2仅需输出可达用户总数),其余场景逻辑一致。
- 核心算法:一致采用「广度优先搜索(BFS)」遍历有向图,保证最短路径(A1)和可达性统计(A2),BFS适合处理无权图的最短路径和可达性问题。
- 优化点:使用队列存储待遍历节点,避免重复访问(标记访问状态),邻接表存储图结构节省空间,适配N≤1000、M≤10000的输入规模。
A1(输入直接表示传播方向,输出每个用户的距离与路径)
题目描述 :在一个社交网络中,有 N 个用户,用户之间存在 M 条单向关注关系。当某个用户发布消息时,该消息会沿着关注链传播:每个收到消息的用户会将该消息转发给自己所有的粉丝。要求:每个用户最多接收一次消息。给定消息的起始发布者,请计算最终会有多少个用户接收到该消息。
运行条件 :
总时限:5000 毫秒
单组时限:1000 毫秒
总内存:320 MB
单组内存:64 MB
输入格式 :
输入数据,格式如下:
第一行:三个整数 N、M、source,以单个空格分隔
N:用户数量,满足 1 ≤ N ≤ 1000
M:关注关系数量,满足 0 ≤ M ≤ 10000
source:消息起始发布者的用户编号,满足 0 ≤ source ≤ N-1
随后 M 行:每行两个整数 u v,以单个空格分隔
表示用户 u 关注用户 v(即 u→v 的消息传播方向)
u 和 v 均为有效用户编号,满足 0 ≤ u,v ≤ N-1
保证不存在自环(即 u ≠ v)
同一关注关系不会重复出现
输出格式 :
按用户编号从 0 到 N-1 依次输出
每行格式为:
若用户不可达:i:-1
若用户可达:i:距离 路径
距离为从 source 到 i 的最短路径长度(整数)
路径为用->连接的编号序列,如 0->1->3
输出时,距离与路径之间,使用单个空格分隔
source 到自身的距离为 0,路径为自身编号
除路径中->外,不使用其他符号或空格
每行以换行结束
输入输出样例:
-
样例1:
输入 :plaintext6 7 0 0 1 0 2 1 2 1 3 2 3 2 4 3 5输出 :
plaintext0:0 0 1:1 0->1 2:1 0->2 3:2 0->1->3 4:2 0->2->4 5:3 0->1->3->5解释:构建的图结构:
用户0可以传播给用户1和用户2
用户1可以传播给用户2和用户3
用户2可以传播给用户3和用户4
用户3可以传播给用户5
传播路径:
用户0 → 用户1, 用户2(距离1)
用户1 → 用户3(距离2)
用户2 → 用户4(距离2)
用户3 → 用户5(距离3) -
样例2:
输入 :plaintext5 4 1 1 0 1 2 2 3 3 4输出 :
plaintext0:1 1->0 1:0 1 2:1 1->2 3:2 1->2->3 4:3 1->2->3->4解释:构建的图结构:
用户1可以传播给用户0和用户2
用户2可以传播给用户3
用户3可以传播给用户4
传播路径:
用户1 → 用户0, 用户2(距离1)
用户2 → 用户3(距离2)
用户3 → 用户4(距离3)
所有用户都可以从用户1到达
python
import sys
from collections import deque
def calculate_message_propagation():
# 读取所有输入数据并转换为迭代器,方便逐个获取数值
input_data = sys.stdin.read().strip().split()
if not input_data:
return
iter_tokens = iter(input_data)
# 解析N(用户数)、M(关注关系数)、source(起始用户)
user_count = int(next(iter_tokens))
relation_count = int(next(iter_tokens))
start_user = int(next(iter_tokens))
# 构建邻接表表示有向图:graph[u]存储u的关注者(消息传播目标)
graph = [[] for _ in range(user_count)]
for _ in range(relation_count):
u = int(next(iter_tokens))
v = int(next(iter_tokens))
graph[u].append(v)
# 初始化距离数组:distance[i]表示start到i的最短距离,-1表示不可达
distance = [-1] * user_count
# 初始化父节点数组:parent[i]表示i在最短路径中的前驱节点,用于回溯路径
parent = [-1] * user_count
# BFS队列,起始节点入队
bfs_queue = deque([start_user])
distance[start_user] = 0 # 起始节点到自身距离为0
# 执行BFS遍历,计算最短距离和父节点
while bfs_queue:
current = bfs_queue.popleft()
# 遍历当前节点的所有传播目标
for neighbor in graph[current]:
if distance[neighbor] == -1: # 未访问过
distance[neighbor] = distance[current] + 1 # 距离+1
parent[neighbor] = current # 记录前驱
bfs_queue.append(neighbor) # 入队待处理
# 生成输出结果
output_lines = []
for user_id in range(user_count):
if distance[user_id] == -1:
# 不可达用户输出格式
output_lines.append(f"{user_id}:-1")
else:
# 回溯路径:从当前用户反向找到起始节点,再反转得到正向路径
path = []
current_node = user_id
while current_node != -1:
path.append(str(current_node))
current_node = parent[current_node]
path.reverse() # 反转得到从start到user_id的路径
# 可达用户输出格式:编号:距离 路径
output_lines.append(f"{user_id}:{distance[user_id]} " + "->".join(path))
# 输出所有结果行
sys.stdout.write("\n".join(output_lines))
if __name__ == "__main__":
calculate_message_propagation()
A2(输入关注关系为v关注u,输出可达用户总数)
题目描述 :在一个社交网络中,有N个用户,用户之间存在M条单向关注关系。当某个用户发布消息时,该消息会沿着关注链传播:每个收到消息的用户会将该消息转发给自己所有的粉丝。要求:每个用户最多接收一次消息。给定消息的起始发布者,请计算最终会有多少个用户接收到该消息。
运行条件:
-
总时限:5000毫秒
-
单组时限:1000毫秒
-
总内存:320 MB
-
单组内存:64 MB
输入格式 :
(1)第一行:三个整数N、M、source,以单个空格分隔
N:用户数量,满足1 ≤ N ≤ 1000
M:关注关系数量,满足0 ≤ M ≤ 10000
source:消息起始发布者的用户编号,满足0 ≤ source ≤ N-1
(2)随后M行:每行两个整数u v,以单个空格分隔
表示用户v关注用户u(即v ← u的消息传播方向)
u和v均为有效用户编号,满足0 ≤ u,v ≤ N-1
保证不存在自环(即u ≠ v)
同一关注关系不会重复出现
输出格式 :
(1)一个整数,表示从起始用户开始,通过消息传播能够到达的用户总数
(2)如果只有起始用户自己接收到消息,输出1
(3)如果无法传播给任何其他用户,输出1(起始用户自己)
(4)最大不超过用户总数N
输入输出样例: -
样例1:
输入 :plaintext5 4 0 1 0 2 0 3 1 4 2输出 :
plaintext5示例1解释:从用户0开始传播:
用户0 → 用户1,用户2(用户1和用户2关注用户0)
用户1 → 用户3(用户3关注用户1)
用户2 → 用户4(用户4关注用户2)
最终所有5个用户都收到消息,输出5 -
样例2:
输入 :plaintext4 3 0 1 0 2 1 3 2输出 :
plaintext4示例2解释:从用户0开始传播:
用户0 → 用户1(用户1关注用户0)
用户1 → 用户2(用户2关注用户1)
用户2 → 用户3(用户3关注用户2)
形成一条传播链:0→1→2→3,所有4个用户都收到消息
提示信息 :
(1)仅包含整数值
(2)不包含任何额外字符、空格或换行等
python
import sys
from collections import deque
def count_reachable_users():
# 读取所有输入数据并转换为整数列表
input_values = list(map(int, sys.stdin.read().split()))
if not input_values:
sys.exit() # 无输入时退出
# 解析前三个值:N(用户数)、M(关系数)、source(起始用户)
user_total = input_values[0]
relation_total = input_values[1]
start_node = input_values[2]
# 构建邻接表:adj_list[u]存储关注u的用户(即u的消息可传播到的对象)
adj_list = [[] for _ in range(user_total)]
idx = 3 # 从第4个元素开始解析M条关系
for _ in range(relation_total):
u = input_values[idx]
v = input_values[idx + 1]
idx += 2
adj_list[u].append(v) # v关注u,u→v传播
# 访问标记数组:visited[i]表示用户i是否已接收消息
visited = [False] * user_total
# BFS队列,起始用户入队并标记为已访问
bfs_queue = deque([start_node])
visited[start_node] = True
# 统计可达用户数,初始为0(后续队列中逐个计数)
reachable_count = 0
# BFS遍历所有可达节点
while bfs_queue:
current_user = bfs_queue.popleft()
reachable_count += 1 # 计数当前用户
# 遍历当前用户的所有传播目标(关注当前用户的人)
for next_user in adj_list[current_user]:
if not visited[next_user]:
visited[next_user] = True # 标记为已访问
bfs_queue.append(next_user) # 入队待处理
# 输出可达用户总数
print(reachable_count)
if __name__ == "__main__":
count_reachable_users()
B类-字符串编辑距离与相似度计算问题
相似题目差异总结:
- 核心差异:输入格式不同(B1为两个字符串用英文逗号分隔,B2为两个字符串分两行输入),其余计算逻辑(编辑距离、相似度)完全一致。
- 核心算法:一致采用「动态规划(DP)」计算编辑距离,状态转移方程涵盖插入、删除、替换三种操作,时间复杂度O(n*m),适配字符串长度≤1000的约束。
- 优化点:使用滚动数组(一维DP数组)替代二维DP数组,节省空间(从O(n*m)优化为O(min(n,m))),计算时忽略大小写统一处理,提高鲁棒性。
B1(输入为逗号分隔的两个字符串,输出编辑距离与相似度)
题目描述 :在文本处理和自然语言处理中,编辑距离是衡量两个字符串相似度的常用指标。它表示通过插入、删除或者替换操作将一个字符串转换为另一个字符串所需的最少次数。
1.编辑距离计算规划
编辑距离通过计算以下三种基本操作的次数来确定:
(1) 插入:在字符串中插入一个字符
(2) 删除:从字符串中删除一个字符
(3) 替换:将字符串中的一个字符替换为另一个字符
2.相似度计算
相似度 = (1 - 编辑距离 / 两个字符串中较长字符串的长度) × 100%
3.任务要求
编写程序,输入两个字符串,计算它们的编辑距离和相似度百分比。
运行条件:
-
总时限:5000 毫秒
-
单组时限:1000 毫秒
-
总内存:320 MB
-
单组内存:64 MB
输入格式 :
格式:字符串A,字符串B (用单个英文逗号分隔,即: 字符串A,字符串B)
输出格式 :
第一行输出编辑距离(整数)
第二行输出相似度百分比(保留两位小数,后跟百分号,如:21.34%)
输入输出样例: -
样例1:
输入 :plaintextkitten,sitting输出 :
plaintext3 57.14%解释:将"kitten"转换为"sitting"需要3次操作,"k"替换为"s" → "sitten","e"替换为"i" → "sittin",插入"g" → "sitting"。相似度计算:
(1)编辑距离 = 3
(2)较长字符串长度 = max(6, 7) = 7
(3)相似度 = (1 - 3/7) × 100% = 57.14% -
样例2:
输入 :plaintextbook,back输出 :
plaintext2 50.00%解释:将"book"转换为"back"需要2次操作,"o"替换为"a" → "baok","o"替换为"c" → "back"。相似度计算:
(1)编辑距离 = 2
(2)较长字符串长度 = max(4, 4) = 4
(3)相似度 = (1 - 2/4) × 100% = (1 - 0.5) × 100%% = 0.5 × 100% = 50.00%
提示信息 :一定要仔细查看提示信息
约束条件:
(1)输入字符串长度在1到1000之间
(2)字符串可以包含大小写字母、数字(不包含空格)
(3)计算时,不区分大小写
python
def calculate_edit_distance_and_similarity():
# 读取输入并按逗号分割为两个字符串,去除首尾空白
input_str = input().strip()
str1, str2 = input_str.split(',')
# 统一转换为小写,忽略大小写差异
str1_lower = str1.lower()
str2_lower = str2.lower()
# 获取两个字符串的长度
len1 = len(str1_lower)
len2 = len(str2_lower)
# 初始化滚动DP数组:dp_prev存储上一行的DP值,长度为len2+1
dp_prev = list(range(len2 + 1))
# 遍历str1的每个字符(i从1开始,对应DP的行索引)
for i in range(1, len1 + 1):
# 初始化当前行DP数组:dp_curr[0] = i(插入i个字符)
dp_curr = [i] + [0] * len2
# 获取当前str1的字符
char1 = str1_lower[i - 1]
# 遍历str2的每个字符(j从1开始,对应DP的列索引)
for j in range(1, len2 + 1):
char2 = str2_lower[j - 1]
# 计算三种操作的代价
delete_cost = dp_prev[j] + 1 # 删除str1的当前字符
insert_cost = dp_curr[j - 1] + 1 # 插入到str1的当前位置
# 替换代价:字符相同则为0,不同则为1
replace_cost = dp_prev[j - 1] + (0 if char1 == char2 else 1)
# 当前DP值取三种操作的最小值
dp_curr[j] = min(delete_cost, insert_cost, replace_cost)
# 更新上一行DP数组为当前行
dp_prev = dp_curr
# 最终编辑距离为dp_prev[len2]
edit_dist = dp_prev[len2]
# 计算较长字符串的长度
max_len = max(len1, len2)
# 计算相似度(避免max_len为0的极端情况,此处输入长度≥1)
similarity = (1 - edit_dist / max_len) * 100
# 输出结果:编辑距离 + 保留两位小数的相似度
print(edit_dist)
print(f"{similarity:.2f}%")
if __name__ == "__main__":
calculate_edit_distance_and_similarity()
B2(输入为分两行的两个字符串,输出编辑距离与相似度)
题目描述 :在文本处理和自然语言处理中,编辑距离是衡量两个字符串相似度的常用指标。它表示通过插入、删除或者替换操作将一个字符串转换为另一个字符串所需的最少次数。
1.编辑距离计算规划
编辑距离通过计算以下三种基本操作的次数来确定:
(1)插入:在字符串中插入一个字符
(2)删除:从字符串中删除一个字符
(3)替换:将字符串中的一个字符替换为另一个字符
2.相似度计算
相似度 = (1 - 编辑距离 / 两个字符串中较长字符串的长度) × 100%
3.任务要求
编写程序,输入两个字符串,计算它们的编辑距离和相似度百分比。
运行条件:
-
总时限:5000 毫秒
-
单组时限:1000 毫秒
-
总内存:320 MB
-
单组内存:64 MB
输入格式 :
第一行:字符串A
第二行:字符串B
输出格式 :
第一行输出编辑距离(整数)
第二行输出相似度百分比(保留两位小数,后跟百分号,如:21.34%)
输入输出样例: -
样例1:
输入 :plaintextkitten sitting输出 :
plaintext3 57.14%示例1解释:将"kitten"转换为"sitting"需要3次操作,"k"替换为"s"→"sitten","e"替换为"i"→"sittin",插入"g"→"sitting"。相似度计算:
(1)编辑距离 = 3
(2)较长字符串长度 = max(6, 7) = 7
(3)相似度 = (1 - 3/7) × 100% = 57.14% -
样例2:
输入 :plaintextbook back输出 :
plaintext2 50.00%示例2解释:将"book"转换为"back"需要2次操作,"o"替换为"a"→"baok","o"替换为"c"→"back"。相似度计算:
(1)编辑距离 = 2
(2)较长字符串长度 = max(4, 4) = 4
(3)相似度 = (1 - 2/4) × 100% = (1 - 0.5) × 100% = 0.5 × 100% = 50.00%
提示信息 :一定要仔细查看提示信息
(1)输入字符串长度在1到1000之间
(2)字符串可以包含大小写字母和数字
(3)计算时,不区分大小写
python
import sys
def compute_edit_and_similarity():
# 读取两行输入,去除首尾空白(避免换行符和空格干扰)
str_a = sys.stdin.readline().rstrip().lower()
str_b = sys.stdin.readline().rstrip().lower()
# 获取字符串长度
len_a = len(str_a)
len_b = len(str_b)
# 初始化滚动DP数组:prev_dp存储上一轮的结果,长度为len_b+1
prev_dp = list(range(len_b + 1))
# curr_dp存储当前轮的结果,临时初始化
curr_dp = [0] * (len_b + 1)
# 遍历str_a的每个字符(i为当前字符索引,从1开始对应DP的行)
for i in range(1, len_a + 1):
curr_dp[0] = i # 第0列:str2为空,需要删除i个字符
curr_char_a = str_a[i - 1]
# 遍历str_b的每个字符(j为当前字符索引,从1开始对应DP的列)
for j in range(1, len_b + 1):
curr_char_b = str_b[j - 1]
# 计算三种操作的代价
cost_delete = prev_dp[j] + 1 # 删除str_a[i-1]
cost_insert = curr_dp[j - 1] + 1 # 插入str_b[j-1]到str_a
# 替换代价:字符相同则无代价,不同则+1
cost_replace = prev_dp[j - 1] if (curr_char_a == curr_char_b) else prev_dp[j - 1] + 1
# 取最小代价作为当前DP值
curr_dp[j] = min(cost_delete, cost_insert, cost_replace)
# 交换prev_dp和curr_dp,准备下一轮迭代(避免重复创建数组)
prev_dp, curr_dp = curr_dp, prev_dp
# 编辑距离为最后一轮的最后一个元素
edit_distance = prev_dp[len_b]
# 较长字符串长度
max_length = max(len_a, len_b)
# 计算相似度
similarity_percent = (1 - edit_distance / max_length) * 100
# 输出结果
print(edit_distance)
print("{:.2f}%".format(similarity_percent))
if __name__ == "__main__":
compute_edit_and_similarity()
C类-矩阵路径搜索问题(向右/向下固定步长移动)
相似题目差异总结:
- 核心差异:输入格式不同(C1的N、M及矩阵元素用英文逗号分隔,C2用单个空格分隔),其余移动规则(向右/向下、步长等于当前格子数字)和输出要求(路径坐标列表或空列表)一致。
- 核心算法:C1采用「BFS+路径回溯」,C2采用「深度优先搜索(DFS)+记忆化失败节点」,均能找到任意一条有效路径,BFS适合找最短路径(本题无长度要求),DFS递归实现简洁,均需避免重复访问无效节点。
- 优化点:标记已访问节点(C1)或失败节点(C2),避免重复搜索,邻接节点仅考虑向右和向下且不越界的情况,适配N、M≤100的矩阵规模。
C1(输入用逗号分隔,BFS实现路径搜索)
题目描述 :给定一个 N × M 的矩阵,每个格子包含一个数字(0-9)。从左上角(0,0)出发,要到达右下角 (N-1, M-1)。移动规则如下:
1.每次只能向右或向下移动。
2.从格子 (i,j) 移动到下一个格子时,移动的步长必须等于当前格子的数字值。
3.如果当前格子数字为 k,那么你只能移动到:
-
(i, j+k)(向右移动 k 步)
-
(i+k, j)(向下移动 k 步)
请找出任意一条从左上角到达右下角的路径。如果存在多条路径,输出任意一条即可;如果无法到达,输出空列表。
运行条件: -
总时限:5000毫秒
-
单组时限:1000毫秒
-
总内存:320 MB
-
单组内存:64 MB
输入格式 :
输入格式如下:
第一行:两个整数 N 和 M(1 ≤ N, M ≤ 100),使用1个英文逗号隔开,即:N,M
接下来 N 行:每行 M 个由1个逗号分隔的整数。
输出格式 :
整个路径用一个列表表示,包含路径上经过的格子坐标,按顺序从起点到终点
列表中的每个元素是一个坐标元组,格式为(x,y)
在数字、逗号和括号之间不能包含任何空格
如果无法到达,输出空列表[]
说明:本题输入输出中,涉及的提示等信息提示符,都使用英语字符。且各部分之间不包含空格。
输入输出样例: -
样例1:
输入 :plaintext3,3 2,1,2 1,0,2 0,1,1输出 :
plaintext[(0,0),(0,2),(2,2)]解释:从(0,0)数字2向右移动2步到(0,2),再从(0,2)数字2向下移动2步到(2,2)到达终点。
-
样例2:
输入 :plaintext4,4 1,3,0,2 2,0,1,1 0,2,0,1 1,1,2,0输出 :
plaintext[(0,0),(1,0),(1,2),(1,3),(2,3),(3,3)]解释:路径:(0,0)→(1,0)→(1,2)→(3,2)→(3,3)。在(1,0)数字2向右移动2步到(1,2),在(1,2)数字1向下移动1步到(2,2)但数字为0无法继续,因此选择向下移动1步到(3,2),最后在(3,2)数字2向右移动2步到(3,4)超出边界,但向右移动1步到(3,3)到达终点。
python
import sys
from collections import deque
def find_matrix_path():
# 读取第一行:N和M(矩阵行数和列数)
first_line = sys.stdin.readline().strip()
if not first_line:
print("[]")
return
# 按逗号分割并转换为整数
rows, cols = map(int, first_line.split(','))
# 读取矩阵数据
matrix = []
for _ in range(rows):
line = sys.stdin.readline().strip()
row_data = list(map(int, line.split(',')))
matrix.append(row_data)
# 特殊情况:矩阵只有一个格子(起点即终点)
if rows == 1 and cols == 1:
print("[(0,0)]")
return
# 访问标记矩阵:记录是否已访问该格子(避免重复)
visited = [[False for _ in range(cols)] for _ in range(rows)]
# 父节点矩阵:记录每个格子的前驱坐标,用于回溯路径
parent = [[None for _ in range(cols)] for _ in range(rows)]
# BFS队列:存储待访问的坐标(x,y)
bfs_queue = deque()
# 起点(0,0)初始化
visited[0][0] = True
bfs_queue.append((0, 0))
# 终点坐标
target_x, target_y = rows - 1, cols - 1
found = False # 标记是否找到路径
# 执行BFS搜索
while bfs_queue and not found:
x, y = bfs_queue.popleft()
current_step = matrix[x][y] # 当前格子的步长
# 步长为0时无法移动,跳过
if current_step == 0:
continue
# 生成两个可能的移动方向:向右、向下
directions = [
(x, y + current_step), # 向右移动current_step步
(x + current_step, y) # 向下移动current_step步
]
# 遍历每个可能的移动方向
for nx, ny in directions:
# 检查新坐标是否在矩阵范围内且未被访问
if 0 <= nx < rows and 0 <= ny < cols and not visited[nx][ny]:
visited[nx][ny] = True # 标记为已访问
parent[nx][ny] = (x, y) # 记录前驱
bfs_queue.append((nx, ny)) # 入队
# 检查是否到达终点
if nx == target_x and ny == target_y:
found = True
break # 找到路径,退出方向遍历
if found:
break # 退出BFS循环
# 未找到路径,输出空列表
if not found:
print("[]")
return
# 回溯路径:从终点反向找到起点,再反转
path = []
curr_x, curr_y = target_x, target_y
while (curr_x, curr_y) != (0, 0):
path.append((curr_x, curr_y))
curr_x, curr_y = parent[curr_x][curr_y]
path.append((0, 0)) # 添加起点
path.reverse() # 反转得到正向路径
# 格式化输出路径:[(x1,y1),(x2,y2),...]
path_str = '[' + ','.join(f'({x},{y})' for x, y in path) + ']'
print(path_str)
if __name__ == "__main__":
find_matrix_path()
C2(输入用空格分隔,DFS实现路径搜索)
题目描述 :给定一个 N×M 的矩阵,每个格子包含一个数字(0-9)。从左上角(0,0)出发,要到达右下角 (N-1,M-1)。移动规则如下:
1.每次只能向右或向下移动。
2.从格子 (i,j) 移动到下一个格子时,移动的步长必须等于当前格子的数字值。
3.如果当前格子数字为 k,那么你只能移动到:
-
(i, j+k)(向右移动 k 步)
-
(i+k, j)(向下移动 k 步)
请找出任意一条从左上角到达右下角的路径。如果存在多条路径,输出任意一条即可;如果无法到达,输出空列表。
运行条件: -
总时限:5000毫秒
-
单组时限:1000毫秒
-
总内存:320 MB
-
单组内存:64 MB
输入格式 :
格式如下:
(1)第一行:两个整数 N 和 M(1 ≤ N, M ≤ 100),用单个空格分隔,即:N M
(2)接下来 N 行:每行 M 个整数,表示矩阵元素,范围 [0,9],中间以单个空格分隔
输出格式 :
(1)整个路径用一个列表表示,包含路径上经过的格子坐标,按顺序从起点到终点
(2)列表中的每个元素是一个坐标元组,格式为(x,y)
(3)在数字、逗号和括号之间不能包含任何空格
(4)如果起点和终点之间没有可行的路径,输出空列表[]
输入输出样例: -
样例1:
输入 :plaintext3 3 2 1 2 1 0 2 0 1 1输出 :
plaintext[(0,0),(0,2),(2,2)]示例1解释:从(0,0)数字2向右移动2步到(0,2),再从(0,2)数字2向下移动2步到(2,2)到达终点。
-
样例2:
输入 :plaintext4 4 1 3 0 2 2 0 1 1 0 2 0 1 1 1 2 0输出 :
plaintext[(0,0),(1,0),(1,2),(1,3),(2,3),(3,3)]示例2解释:路径:(0,0)→(1,0)→(1,2)→(3,2)→(3,3)。所有移动都遵循"移动步长等于当前格子数字"的规则,且只向右或向下移动。
提示信息 :一定要仔细查看提示信息
本题输入输出中,涉及的提示等信息提示符,都使用英语字符。且各部分之间不包含空格。
python
import sys
# 增加递归深度限制,适配最大100x100矩阵的搜索深度
sys.setrecursionlimit(5000)
def search_matrix_path():
# 读取所有输入数据并转换为迭代器
input_data = sys.stdin.read().split()
if not input_data:
return
data_iter = iter(input_data)
# 解析矩阵行数N和列数M
try:
rows = int(next(data_iter))
cols = int(next(data_iter))
except StopIteration:
return # 输入不完整,直接返回
# 构建矩阵:读取N行,每行M个元素
matrix = []
for _ in range(rows):
current_row = []
for _ in range(cols):
current_row.append(int(next(data_iter)))
matrix.append(current_row)
# 标记失败节点:failed[x][y]表示从(x,y)出发无法到达终点,避免重复搜索
failed = [[False for _ in range(cols)] for _ in range(rows)]
# 存储找到的路径(坐标字符串形式,如"(0,0)")
result_path = []
# DFS递归函数:从(x,y)出发搜索路径
def dfs(x, y):
# 将当前坐标加入路径
result_path.append(f"({x},{y})")
# 递归终止条件:到达终点
if x == rows - 1 and y == cols - 1:
return True
# 获取当前格子的步长
step = matrix[x][y]
# 步长为0无法移动,标记为失败并回溯
if step == 0:
result_path.pop()
failed[x][y] = True
return False
# 尝试向右移动:(x, y+step)
if y + step < cols:
if not failed[x][y + step]:
if dfs(x, y + step):
return True
# 尝试向下移动:(x+step, y)
if x + step < rows:
if not failed[x + step][y]:
if dfs(x + step, y):
return True
# 两种方向都无法到达终点,标记为失败并回溯
result_path.pop()
failed[x][y] = True
return False
# 从起点(0,0)开始DFS
if dfs(0, 0):
# 路径存在,格式化输出
print("[" + ",".join(result_path) + "]")
else:
# 路径不存在,输出空列表
print("[]")
if __name__ == "__main__":
search_matrix_path()
D类-改进型移位密码加密问题
相似题目差异总结:
- 核心差异:输入格式不同(D1为明文和密钥用单个空格分隔,D2为明文和密钥分两行输入),其余加密规则(偏移量计算、字母循环移位、非字母字符保留)完全一致。
- 核心算法:一致采用「ASCII码运算」实现字符移位,按大小写字母分别处理循环(A-Z、a-z),非字母字符直接保留,时间复杂度O(n)(n为明文长度)。
- 优化点:预计算基础偏移量(密钥ASCII码对26取模),避免重复计算;按字符类型分支处理,提高效率;适配含字母、数字、符号的任意明文输入。
D1(输入为空格分隔的明文与密钥,输出加密密文)
题目描述 :一个加密系统使用改进的移位密码对消息进行加密。加密规则如下:
1.对于明文中每个字母字符(包括大小写),将其按照密钥字符确定的偏移量进行移位加密。
2.非字母字符保持不变。
3.偏移量计算方法:取密钥字符的ASCII码值对26取模,得到基础偏移量(0-25)。
4.每个字符的实际偏移量 = 基础偏移量 + 该字符在字符串中的位置索引。
5.加密时,大写字母在'A''Z'范围内循环移位,小写字母在'a''z'范围内循环移位。
任务要求
编写一个程序,实现对明文的加密功能。程序需要读取输入数据,对待变换的字符串使用指定的变换密钥进行加密,并输出加密后的结果。
运行条件:
-
总时限:5000毫秒
-
单组时限:1000毫秒
-
总内存:320 MB
-
单组内存:64 MB
输入格式 :
输入数据通过空格分隔为两部分:
1.第一部分:待变换的字符串(明文字符串,可包含字母、数字、符号等)
2.第二部分:变换密钥(单个字符)
例如:Python123 B
输出格式 :
1.一行字符串,表示加密后的密文
说明
1.输入必须且只能包含两部分,用单个空格分隔
2.密钥必须是单个字符,不能为空或多个字符
输入输出样例: -
样例1:
输入 :plaintextHELLO A输出 :
plaintextUSABF示例1解释:密钥'A'的ASCII码为65,65 % 26 = 13,因此基础偏移量为13。每个字母的实际偏移量为13+位置索引:
H(位置0):13+0=13 → H→U
E(位置1):13+1=14 → E→S
L(位置2):13+2=15 → L→A
L(位置3):13+3=16 → L→B
O(位置4):13+4=17 → O→F -
样例2:
输入 :plaintextPython t输出 :
plaintextBlhwee解释:密钥"t"的ASCII码为116,116 % 26 = 12,因此基础偏移量为12。每个字母的实际偏移量为12+位置索引:
P(位置0):12+0=12 → P→B
y(位置1):12+1=13 → y→l
t(位置2):12+2=14 → t→h
h(位置3):12+3=15 → h→w
o(位置4):12+4=16 → o→e
n(位置5):12+5=17 → n→e
python
def encrypt_with_shift_cipher():
# 读取输入并按最后一个空格分割(确保明文含空格时也能正确分割,题目说明输入无空格?按题目要求处理)
input_line = input().strip()
# 分割为明文和密钥(最后一个空格为分隔符)
plaintext, key_char = input_line.rsplit(' ', 1)
# 计算基础偏移量:密钥字符ASCII码对26取模
base_offset = ord(key_char) % 26 if key_char else 0
# 存储加密后的字符列表
cipher_chars = []
# 遍历明文中的每个字符,按位置索引计算实际偏移量
for idx, char in enumerate(plaintext):
if 'A' <= char <= 'Z':
# 大写字母处理:A-Z(ASCII 65-90)
char_code = ord(char) - ord('A') # 转换为0-25
# 计算实际偏移量并循环移位
shifted_code = (char_code + base_offset + idx) % 26
cipher_chars.append(chr(shifted_code + ord('A')))
elif 'a' <= char <= 'z':
# 小写字母处理:a-z(ASCII 97-122)
char_code = ord(char) - ord('a') # 转换为0-25
shifted_code = (char_code + base_offset + idx) % 26
cipher_chars.append(chr(shifted_code + ord('a')))
else:
# 非字母字符直接保留
cipher_chars.append(char)
# 拼接字符列表为密文字符串并输出
print(''.join(cipher_chars))
if __name__ == "__main__":
encrypt_with_shift_cipher()
D2(输入为分两行的明文与密钥,输出加密密文)
题目描述 :一个加密系统使用改进的移位密码对消息进行加密。加密规则如下:
(1) 对于明文中每个字母字符(包括大小写),将其按照密钥字符确定的偏移量进行移位加密。
(2) 非字母字符保持不变。
(3) 偏移量计算方法:取密钥字符的ASCII码值对26取模,得到基础偏移量(0-25)。
(4) 每个字符的实际偏移量 = 基础偏移量 + 该字符在字符串中的位置索引。
(5) 加密时,大写字母在'A''Z'范围内循环移位,小写字母在'a''z'范围内循环移位。
任务要求
编写一个程序,输入两行数据,第一行是待加密的明文,第二行是密钥字符,对明文进行加密,并输出加密后的结果。
运行条件:
-
总时限:5000毫秒
-
单组时限:1000毫秒
-
总内存:320 MB
-
单组内存:64 MB
输入格式 :
(1)第一行:待加密的明文(不得包含任何空格)
(2)第二行:一个字符,表示密钥
输出格式 :
一行字符串,表示加密后的密文
输入输出样例: -
样例1:
输入 :plaintextHELLO A输出 :
plaintextUSABF示例1解释:密钥'A'的ASCII码为65,65 % 26 = 13,因此基础偏移量为13。每个字母的实际偏移量为13+位置索引:
H(位置0):13+0=13 → H→U
E(位置1):13+1=14 → E→S
L(位置2):13+2=15 → L→A
L(位置3):13+3=16 → L→B
O(位置4):13+4=17 → O→F -
样例2:
输入 :plaintextPython t输出 :
plaintextBlhwee示例2解释:密钥't'的ASCII码为116,116 % 26 = 12,因此基础偏移量为12。每个字母的实际偏移量为12+位置索引:
P(位置0):12+0=12 → P→B
y(位置1):12+1=13 → y→l
t(位置2):12+2=14 → t→h
h(位置3):12+3=15 → h→w
o(位置4):12+4=16 → o→e
n(位置5):12+5=17 → n→e
提示信息 :一定要仔细查看提示信息
(1)明文不允许包含空格,只能由连续的字符串组成
(2)密钥必须是单个字符
(3)程序应该能够处理各种字符(字母、数字、符号等)
python
def encrypt_text():
# 读取明文(第一行)和密钥(第二行),去除首尾空白(避免换行符干扰)
plaintext = input().strip()
key = input().strip()
# 计算基础偏移量:密钥字符的ASCII码对26取模(密钥为单个字符)
base_offset = ord(key[0]) % 26 if key else 0
# 存储加密后的字符
encrypted_chars = []
# 遍历明文中的每个字符,按索引计算实际偏移量
for pos, char in enumerate(plaintext):
if char.isupper():
# 处理大写字母:A-Z循环
# 转换为0-25的编码,移位后取模,再转换回ASCII
original_code = ord(char) - ord('A')
actual_offset = base_offset + pos
new_code = (original_code + actual_offset) % 26
encrypted_chars.append(chr(new_code + ord('A')))
elif char.islower():
# 处理小写字母:a-z循环
original_code = ord(char) - ord('a')
actual_offset = base_offset + pos
new_code = (original_code + actual_offset) % 26
encrypted_chars.append(chr(new_code + ord('a')))
else:
# 非字母字符(数字、符号等)直接添加,不加密
encrypted_chars.append(char)
# 拼接所有加密字符,输出密文
print(''.join(encrypted_chars))
if __name__ == "__main__":
encrypt_text()
E类-成绩/绩效统计分析问题
相似题目差异总结:
- 核心差异:统计对象不同(E1为员工绩效,E2为学生单科成绩),筛选阈值不同(E1改进员工<70分、优秀员工≥90分;E2不及格学生<60分、优秀学生≥90分),输出标识不同(Improvement/Outstanding vs Fail/Excellent),其余统计逻辑(平均分、最高分、最低分)一致。
- 核心算法:一致采用「遍历统计」策略,计算总分求平均,遍历找出极值和符合条件的对象,时间复杂度O(n)(n为统计对象数量)。
- 优化点:读取输入时过滤空行,分离姓名与分数存储,避免重复遍历(一次遍历完成分数统计和对象筛选),平均分保留两位小数适配输出要求。
E1(员工绩效统计,改进阈值70分,优秀阈值90分)
题目描述 :实现一个简单的员工绩效分析系统,能够统计员工的绩效得分情况,包括平均分、最高分、最低分,并找出需要改进和表现优秀的员工。
功能要求
1.数据输入 - 读取员工姓名和绩效得分
2.绩效统计 - 计算平均分、最高分、最低分
3.改进名单 - 找出得分低于70分的员工
4.优秀名单 - 找出得分达到90分以上的员工
运行条件:
-
总时限:5000毫秒
-
单组时限:1000毫秒
-
总内存:320 MB
-
单组内存:64 MB
输入格式 :
输入多行数据:
1.第一行:部门名称
2.后续每行:员工姓名和绩效得分,用一个英文冒号分隔,即:员工姓名:绩效得分
输出格式 :
1.第一段:部门统计信息,格式为"[Department]-average:[平均值],max:[最大值],min:[最小值]"
2.第二段:需要改进员工名单,格式为"Improvement:[员工1],[员工2],..."
3.第三段:优秀员工名单,格式为"Outstanding:[员工1],[员工2],..."
4.平均分保留2位小数
5.如果没有需要改进或优秀员工,相应部分显示"None"
说明:本题输入输出中,涉及的提示、统计等信息提示符,都使用英语字符。且各部分之间不包含空格。
输入输出样例: -
样例1:
输入 :plaintextEngineering Alice:85 Bob:65 Charlie:92 David:58 Eve:78输出 :
plaintextEngineering-average:75.60,max:92,min:58 Improvement:Bob,David Outstanding:Charlie解释:Engineering部门共有5名员工参与评估,统计结果为:平均分75.60分(85+65+92+58+78)/5,最高分:92分(Charlie),最低分:58分(David)需要改进员工:Bob(65分)、David(58分)(分数低于70分)优秀员工:Charlie(92分)(分数达到90分及以上)
-
样例2:
输入 :plaintextMarketing John:45 Mary:88 Tom:62 Lisa:91输出 :
plaintextMarketing-average:71.50,max:91,min:45 Improvement:John,Tom Outstanding:Lisa解释:Marketing部门共有4名员工参与评估,统计结果为:平均分71.50分(45+88+62+91)/4,最高分:91分(Lisa),最低分:45分(John)需要改进员工:John(45分)、Tom(62分)(分数低于70分)优秀员工:Lisa(91分)(分数达到90分及以上)
python
import sys
def analyze_employee_performance():
# 读取所有输入行,过滤空行(去除首尾空白后为空的行)
input_lines = [line.strip() for line in sys.stdin.readlines() if line.strip()]
if not input_lines:
return # 无输入数据,直接退出
# 第一行为部门名称
dept_name = input_lines[0]
# 解析后续行的员工姓名和绩效得分
employee_records = [] # 存储元组(姓名, 得分)
for line in input_lines[1:]:
# 按英文冒号分割姓名和得分,最多分割1次(避免姓名含冒号,题目保证格式正确)
name, score_str = line.split(':', 1)
score = int(score_str)
employee_records.append((name, score))
# 提取所有得分,用于计算统计指标
scores = [score for _, score in employee_records]
total_employees = len(employee_records)
# 计算平均分、最高分、最低分
average_score = sum(scores) / total_employees
max_score = max(scores)
min_score = min(scores)
# 生成部门统计信息行
stats_line = f"{dept_name}-average:{average_score:.2f},max:{max_score},min:{min_score}"
print(stats_line)
# 筛选需要改进的员工(得分<70)和优秀员工(得分≥90)
improvement_list = [name for name, score in employee_records if score < 70]
outstanding_list = [name for name, score in employee_records if score >= 90]
# 输出改进员工名单:无则显示None
improvement_output = "Improvement:" + (",".join(improvement_list) if improvement_list else "None")
print(improvement_output)
# 输出优秀员工名单:无则显示None
outstanding_output = "Outstanding:" + (",".join(outstanding_list) if outstanding_list else "None")
print(outstanding_output)
if __name__ == "__main__":
analyze_employee_performance()
E2(学生成绩统计,不及格阈值60分,优秀阈值90分)
题目描述 :实现一个简单的单科成绩分析系统,能够统计学生的成绩情况,包括平均分、最高分、最低分,并找出不及格和优秀的学生。
功能要求:
1.数据输入 - 读取学生姓名和单科成绩。
2.成绩统计 - 计算平均分、最高分、最低分。
3.不及格名单 - 找出成绩低于60分的学生。
4.优秀名单 - 找出成绩达到90分以上的学生。
运行条件:
-
总时限:5000毫秒
-
单组时限:1000毫秒
-
总内存:320 MB
-
单组内存:64 MB
输入格式 :
输入多行数据:
(1)第一行:科目名称
(2)后续每行:学生姓名和成绩,用一个英文冒号分隔,即:学生姓名:分数
输出格式 :
(1)第一段:科目统计信息,格式为"[Subject]-average:[平均分],max:[最高分],min:[最低分]"
(2)第二段:不及格学生名单,格式为"Fail:[学生1],[学生2],..."
(3)第三段:优秀学生名单,格式为"Excellent:[学生1],[学生2],..."
(4)平均分保留2位小数
(5)如果没有不及格或优秀学生,相应部分显示"None"
输入输出样例: -
样例1:
输入 :plaintextMathematics Alice:85 Bob:92 Charlie:58 Dave:76 Eve:95输出 :
plaintextMathematics-average:81.20,max:95,min:58 Fail:Charlie Excellent:Bob,Eve示例1解释:科目Mathematics共有5名学生,平均分81.20,最高分95,最低分58,Charlie不及格,Bob和Eve优秀。
-
样例2:
输入 :plaintextPhysics John:45 Mary:88 Tom:62 Lisa:91输出 :
plaintextPhysics-average:71.50,max:91,min:45 Fail:John Excellent:Lisa示例2解释:科目Physics共有4名学生,平均分71.50,最高分91,最低分45,John不及格,Lisa优秀。
提示信息 :一定要仔细查看提示信息
本题输入输出中,涉及的提示、统计等信息提示符,都使用英语字符。且各部分之间不包含空格。
python
import sys
def analyze_student_grades():
# 读取所有输入行,过滤空行(去除首尾空白后为空的行)
input_content = [line.strip() for line in sys.stdin.read().splitlines() if line.strip()]
if not input_content:
return
# 第一行为科目名称
subject = input_content[0]
# 存储学生姓名和成绩的列表
student_grades = []
# 存储所有成绩,用于统计
all_scores = []
# 解析学生数据(从第二行开始)
for line in input_content[1:]:
# 按英文冒号分割姓名和成绩
name, score_str = line.split(":", 1)
score = int(score_str)
student_grades.append((name, score))
all_scores.append(score)
# 计算统计指标
total_students = len(student_grades)
average = sum(all_scores) / total_students
highest_score = max(all_scores)
lowest_score = min(all_scores)
# 输出科目统计信息
print(f"{subject}-average:{average:.2f},max:{highest_score},min:{lowest_score}")
# 筛选不及格学生(<60分)和优秀学生(≥90分)
fail_students = []
excellent_students = []
for name, score in student_grades:
if score < 60:
fail_students.append(name)
if score >= 90:
excellent_students.append(name)
# 输出不及格名单
if fail_students:
print("Fail:" + ",".join(fail_students))
else:
print("Fail:None")
# 输出优秀名单
if excellent_students:
print("Excellent:" + ",".join(excellent_students))
else:
print("Excellent:None")
if __name__ == "__main__":
analyze_student_grades()