
4557: [JLoi2016]侦察守卫
发布日期:2021-05-06 23:47:40
浏览次数:20
分类:精选文章
本文共 3340 字,大约阅读时间需要 11 分钟。
为了解决这个问题,我们需要找到一种方法来放置侦查守卫,使得所有B神可能出现的位置都被监视,同时代价最小。我们可以利用树的结构和动态规划来高效地解决这个问题。
方法思路
树的结构分析:给定的地图是一棵树,树的结构使得任意两个点之间有且只有一条路径。我们可以利用树的结构进行深度优先搜索(DFS)来处理每个节点及其子节点。
动态规划的使用:我们使用动态规划来记录每个节点覆盖不同层数的最小代价。定义两个数组f[i][k]
和g[i][k]
,分别表示以节点i为根,覆盖k层的最小代价和覆盖k层的节点的最小代价。
状态转移:在处理每个子节点时,考虑是否在当前节点放置守卫,或者在父节点放置,以达到最小代价。通过递归地处理每个子树,并在每一步中选择最优的位置。
覆盖范围处理:由于每个守卫能够监视D层范围内的节点,我们在动态规划中考虑每个节点的覆盖范围,确保所有可能的B神位置被覆盖。
解决代码
import sysfrom collections import dequedef main(): sys.setrecursionlimit(1 << 25) n, d = map(int, sys.stdin.readline().split()) w = list(map(int, sys.stdin.readline().split())) m = int(sys.stdin.readline()) targets = list(map(int, sys.stdin.readline().split())) edges = [[] for _ in range(n+1)] for _ in range(n-1): u, v = map(int, sys.stdin.readline().split()) edges[u].append(v) edges[v].append(u) visited = [False] * (n + 1) parent = [0] * (n + 1) children = [[] for _ in range(n + 1)] q = deque() q.append(1) visited[1] = True while q: u = q.popleft() for v in edges[u]: if not visited[v]: visited[v] = True parent[v] = u children[u].append(v) q.append(v) target_set = set(targets) f = [[0] * (d + 1) for _ in range(n + 1)] g = [[0] * (d + 1) for _ in range(n + 1)] stack = [] visited_dp = [False] * (n + 1) stack.append((1, 0)) while stack: node, depth = stack.pop() if visited_dp[node]: continue visited_dp[node] = True for child in children[node]: stack.append((child, depth + 1)) post_order = [] stack = [(1, False)] while stack: node, processed = stack.pop() if processed: post_order.append(node) continue stack.append((node, True)) for child in children[node]: stack.append((child, False)) for u in post_order: f[u][0] = w[u] g[u][0] = 1 for k in range(1, d + 1): f[u][k] = float('inf') g[u][k] = float('inf') for child in children[u]: for k in range(d + 1): if f[child][k] == float('inf'): continue if f[u][k] > f[child][k] + w[u]: f[u][k] = f[child][k] + w[u] g[u][k] = g[child][k] + 1 if g[u][k] > g[child][k] + 1: g[u][k] = g[child][k] + 1 for k in range(d, 0, -1): if f[u][k] > f[u][k-1]: f[u][k] = f[u][k-1] if g[u][k] > g[u][k-1]: g[u][k] = g[u][k-1] for k in range(1, d + 1): f[u][k] = min(f[u][k], f[u][k-1]) g[u][k] = min(g[u][k], g[u][k-1]) f[u][0] = min(f[u][0], f[u][1]) g[u][0] = min(g[u][0], g[u][1]) res = float('inf') for t in targets: for k in range(d + 1): if g[1][k] >= n: res = min(res, f[1][k]) print(res)if __name__ == "__main__": main()
代码解释
输入处理:读取输入数据,构建树的结构,并确定B神可能出现的位置。
树的构建:使用DFS构建树的父节点和子节点关系。
动态规划初始化:定义两个数组f
和g
,分别记录覆盖不同层数的最小代价和节点数。
动态规划处理:使用后序遍历(post-order)来处理每个节点,计算覆盖不同层数的最小代价。
结果计算:遍历所有可能的B神位置,计算最小代价并输出结果。
通过这种方法,我们能够高效地解决这个问题,确保所有B神可能出现的位置都被覆盖,同时代价最小。
发表评论
最新留言
感谢大佬
[***.8.128.20]2025年04月13日 20时31分31秒
关于作者

喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
2.2.2原码补码移码的作用
2019-03-06
多线程之Lock显示锁
2019-03-06
ForkJoinPool线程池
2019-03-06
【Struts】配置Struts所需类库详细解析
2019-03-06
Java面试题:Servlet是线程安全的吗?
2019-03-06
DUBBO高级配置:多注册中心配置
2019-03-06
Java集合总结系列2:Collection接口
2019-03-06
Linux学习总结(九)—— CentOS常用软件安装:中文输入法、Chrome
2019-03-06
大白话说Java反射:入门、使用、原理
2019-03-06
集合系列 Set(八):TreeSet
2019-03-06
JVM基础系列第11讲:JVM参数之堆栈空间配置
2019-03-06
MySQL用户管理:添加用户、授权、删除用户
2019-03-06
比技术还重要的事
2019-03-06
linux线程调度策略
2019-03-06
软中断和实时性
2019-03-06
Linux探测工具BCC(可观测性)
2019-03-06
Opentelemetry Metrics SDK
2019-03-06
流量控制--2.传统的流量控制元素
2019-03-06
SNMP介绍及使用,超有用,建议收藏!
2019-03-06
SDUT2161:Simple Game(NIM博弈+巴什博弈)
2019-03-06