用Python编写出这个程序

img

img


一艘飞船正在太阳系执行任务,途中遭遇太阳风暴。飞船呈长条状,有n个节点分别装着价值为v同的设
备。节点之间有n-1个连接道路,道路长d,且该道路不受太阳风暴影响。
有一种护盾,能够保护半径为k的范围不受风暴影响,且飞船上载有s个该护盾。
现求安放多少个护盾(<=s),分别在哪些节点上,才能保护价值最多的设备,且保证节点之间是连接的(节点之间道路不必完全在护盾范围里,但两个节点之间的节点如果被破坏,就不算作连接的节点,即不能只保护断开的,价值高的节点)。
输入格式:
第一行3个整数,表示n个节点,S个护盾,护盾半径为k。
第二行n-1个整数,第i个整数表示第;个节点到第i+1个节点的距离。
第三行n个整数,表示节点的价值。
输出格式:
第一行1个整数x,表示安放几个盾牌。
第二行×个整数,表示盾牌安放在第几个节点。

这道题可以采用贪心算法求解。

我们可以先将所有节点按照价值从大到小排序,然后从价值最大的节点开始考虑放置护盾的问题。由于该节点价值最大,我们肯定希望在保护它的前提下,尽可能地保护其他有连接的节点。因此,我们可以先将与该节点相邻的节点全部覆盖,然后再考虑剩下的护盾可以覆盖哪些节点。具体实现可以使用贪心+递归的方式,每一次递归都选择一个未被覆盖的价值最大的节点,然后尽可能地覆盖与之相邻的节点,直到护盾用完或者所有节点都被覆盖。

另外,由于题目中规定了节点之间的连接关系,因此我们可以采用树形结构来表示节点和连接关系。具体实现可以使用邻接矩阵或邻接表来存储。

下面是Python的实现代码:

n, s, k = map(int, input().split())

# 用邻接矩阵表示节点之间的连接关系和距离
G = [[0] * n for _ in range(n)]
for i in range(n - 1):
    d = int(input())
    G[i][i + 1] = G[i + 1][i] = d

# 用列表保存每个节点的价值
values = list(map(int, input().split()))

# 用一个列表保存已经覆盖的节点
covered = [False] * n

# 递归函数,返回当前状态下可以覆盖的节点数量和对应的节点列表
def dfs(node, k, cnt, nodes):
    # 如果护盾用完了或者所有节点都已经被覆盖了,直接返回
    if k == 0 or cnt == n:
        return (cnt, nodes)
    
    # 尽可能地覆盖与当前节点相邻的未被覆盖的节点
    for i in range(n):
        if G[node][i] > 0 and not covered[i]:
            covered[i] = True
            nodes.append(i)
            cnt += 1
            k -= 1
    
    # 选择下一个未被覆盖的节点进行递归
    max_value = 0
    max_nodes = []
    for i in range(n):
        if not covered[i] and values[i] > max_value:
            new_k = min(k, G[node][i] // 2)
            new_cnt, new_nodes = dfs(i, new_k, cnt, nodes[:])
            # 更新最优解
            if new_cnt > cnt or (new_cnt == cnt and sum(values[j] for j in new_nodes) > sum(values[j] for j in max_nodes)):
                max_value = sum(values[j] for j in new_nodes)
                max_nodes = new_nodes
    
    return (cnt, nodes if not max_nodes else max_nodes)

# 将所有节点按照价值从大到小排序
sorted_nodes = sorted(range(n), key=lambda x: -values[x])

# 从价值最大的节点开始尝试安装护盾
result = []
for node in sorted_nodes:
    if not covered[node]:
        covered[node] = True
        cnt, nodes = dfs(node, k, 1, [node])
        # 更新结果
        if not result or cnt > result[0]:
            result = [cnt, nodes]

# 输出结果
print(result[0])
print(*sorted(result[1]))
不知道你这个问题是否已经解决, 如果还没有解决的话:
  • 帮你找了个相似的问题, 你可以看下: https://ask.csdn.net/questions/1090014
  • 除此之外, 这篇博客: 2022年第十三届蓝桥杯研究生Python组题目分享中的 有一根围绕原点 O 顺时针旋转的棒 OA,初始时指向正上方(Y 轴正向)。 在平面中有若干物件,第 i 个物件的坐标为 (xi , yi) ,价值为 zi。当棒扫到某个 物件时,棒的长度会瞬间增长 zi,且物件瞬间消失(棒的顶端恰好碰到物件也 视为扫到),如果此时增长完的棒又额外碰到了其他物件,也按上述方式消去 (它和上述那个点视为同时消失)。 如果将物件按照消失的时间排序,则每个物件有一个排名,同时消失的物 件排名相同,请输出每个物件的排名,如果物件永远不会消失则输出 −1 部分也许能够解决你的问题, 你可以仔细阅读以下内容或者直接跳转源博客中阅读:


如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^