AcWing 树形DP相关问题 323. 战略游戏

import sys
sys.stdin = open('data.txt', 'r')



'''
题目意思本质就是一条边上至少要选一个节点
dp(i, j) 表示在以i为根的子树上做放置士兵的选择,在根节点i选择状态是j的情况下所有可能的选择中最少的士兵数量
(j 只有0, 1两种选择)
'''


def dp(i, j, memo):
    if (i, j) in memo:
        return memo[(i, j)]

    if len(link[i]) == 0:
        memo[(i, j)] = j
        return j

    if j == 0:
        ans = 0
        for child in link[i]:
            ans += dp(child, 1, memo)
    else:
        ans = 1
        for child in link[i]:
            ans += min( dp(child, 1, memo), dp(child, 0, memo))

    memo[(i, j)] = ans
    return ans


while True:
    try:
        N = int(input())
    except:
        break

    link = {}
    parent = [-1] * N
    for i in range(N):
        line = input()

        idx = line.index(':')
        node_id = int(line[:idx])
        idx1, idx2 = line.index('('), line.index(')')
        sub_num = int(line[idx1+1: idx2])
        if sub_num == 0:
            link[node_id] = []
        else:
            link[node_id] = []
            start_idx = idx2 + 1

            while len(link[node_id]) < sub_num:
                ii = start_idx + 1
                while ii < len(line) and line[ii] != ' ':
                    ii += 1

                link[node_id].append(int(line[start_idx+1: ii]))
                start_idx = ii

        for sub in link[node_id]:
            parent[sub] = node_id

    root = 0
    while parent[root] != -1:
        root = parent[root]

    print( min(dp(root, 0, {}), dp(root, 1, {})) )










猜你喜欢

转载自blog.csdn.net/xiaohaowudi/article/details/107751584
今日推荐