题目描述: 为了达到新冠疫情精准防控的需要,为了避免全员核酸检测带来的浪费,需要精准圈定可能被感染的人群。现在根据传染病流调以及大数据分析, 得到了每个人之间在时间、空间上是否存在轨迹的交叉。 现在给定一组确诊人员编号(X1,X2,X3....Xn),在所有人当中,找出哪些人需要进行核酸检测,输出需要进行核酸检测的人数。(注意:确诊病例自身不需要再做核酸检测) 需要进行核酸检测的人,是病毒传播链条上的所有人员,即有可能通过确诊病例所能传播到的所有人。 例如:A是确诊病例,A和B有接触、B和C有接触、C和D有接触、D和E有接触,那么B\C\D\E都是需要进行核酸检测的人。 输入描述: 第一行为总人数N 第二行为确诊病例人员编号(确诊病例人员数量<N),用逗号分割 第三行开始,为一个N*N的矩阵,表示每个人员之间是否有接触,0表示没有接触,1表示有接触。 输出描述: 整数:需要做核酸检测的人数 人员编号从0开始 0<N<100 示例1 输入: 5 1,2 1,1,0,1,0 1,1,0,0,0 0,0,1,0,1 1,0,0,1,0 0,0,1,0,1 输出:3 说明: 编号为1、2号的人员,为确诊病例。1号与0号有接触,0号与3号有接触
解决思路:
1、输入解析:读取总人数 N、确诊病例编号列表、接触矩阵。
2、图的构建:将接触矩阵转换为图的邻接表表示。
3、图的遍历:
·构造状态访问列表visited,visited[i] == 1 表示第i个需要核酸检测
·构造存储接触人员的列表need_test_people
·从每个确诊病例开始,使用DFS遍历图,找到所有与之连通的节点(接触人员)。
4、输出结果:统计所有需要做核酸检测(接触人员)的人数。
代码部分
def count_need_to_test(n, confirmed_cases, contact_relationship):
#确诊病例转换为列表
confirmed_cases_list = list(map(int, confirmed_cases.split(',')))
#访问状态数组
visited = [0] * n
def dfs(case, visited):
# 遍历当前人员与其他所有人的接触情况
for neighbor in range(n):
#存在接触人员,且该人员未曾被其他人接触时
#当neighbor = case时,由于调用dfs函数前,已将visited[case]置为1,会直接跳过此判断,执行下一次循环
if contact_relationship[case][neighbor] == 1 and not visited[neighbor]:
visited[neighbor] = 1
dfs(neighbor, visited)
# 确诊病例标记为已访问
for case in confirmed_cases_list:
visited[case] = 1
dfs(case, visited)
#统计需要做检测的人数
count = sum(visited) - len(confirmed_cases_list) #visited中记为1的序号为全体需要做核酸的人(包括已确诊病人)
all_test_people = [i for i in range(len(visited)) if visited[i] == 1]
need_test_people = [i for i in all_test_people if i not in confirmed_cases_list]
return count, need_test_people
n = int(input())
confirmed_cases = input()
contact_relationship = [list(map(int, input().strip().split(','))) for _ in range(n)]
num, people = count_need_to_test(n, confirmed_cases, contact_relationship)
print(num)
其他思路:
可以直接将visited等存储列表变更为set,使用set.add()操作将确诊病例的密接者加入集合。
代码部分:
def need_to_test(n, confirmed_cases, contact_relationship):
confirmed_cases_set = set(map(int, confirmed_cases.split(',')))
#使用集合确认不重复添加
need_people = set()
visited = set()
def dfs(case, visited):
for neighbor in range(n):
if contact_relationship[case][neighbor] == 1 and neighbor not in visited:
visited.add(neighbor)
need_people.add(neighbor)
dfs(neighbor, visited)
#遍历每个确诊病例
for case in confirmed_cases_set:
visited.add(case)
dfs(case, visited)
#去除确诊病例自身
need_people -= confirmed_cases_set #集合可以直接使用-,表示集合差集 A-B = A-(A&B)
return len(need_people), need_people
知识点:图的遍历(DFS),列表
由于对BFS解法不太熟悉,若有高人也请指点一二
结语:越简单的题目解法应该越多,请路过大神留下新的思路供本小白学习一下,打开思路