2022-02-10 每日打卡:难题精刷

116 阅读2分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

2022-02-10 每日打卡:难题精刷

写在前面

“这些事儿在熟练之后,也许就像喝口水一样平淡,但却能给初学者带来巨大的快乐,我一直觉得,能否始终保持如初学者般的热情、专注,决定了在做某件事时能走多远,能做多好。” 该系列文章由python编写,所刷题目共三个来源:之前没做出来的 ;Leetcode中等,困难难度题目; 周赛题目;某个专题的经典题目,所有代码已AC。每日1-3道,随缘剖析,希望风雨无阻,作为勉励自己坚持刷题的记录。

选课

在这里插入图片描述

刚开始以为是类似最小生成树,使用了贪心+栈的方法。后来发现因为【存在步数限制】,所以不能保证所有的结点都被检查到。也就说明,可能后来更大的分数因为没有走到而被忽略。
所以一个比较显著的思路是dfs,然而最终【选择最优路径】是通过dp来的,原因在于可以选择【当前结点的兄弟结点】或者【沿着当前结点一直走下去】,dp的过程也就是dfs的返回过程,直接写到一起即可。

import collections
m,n = [int(i) for i in input().split(" ")]
pre = collections.defaultdict(list)
ans = [[0 for i in range(n+2)]
             for i in range(m+2)]
for line in range(1,m+1):
    p, q = [int(i) for i in input().split(" ")]
    pre[p].append(line)
    # 从当前开始选择一个结点
    ans[line][1] = q

def dfs(idx):
    for nxt in pre[idx]:
        # 先计算叶结点再计算根结点
        dfs(nxt)
        # 对每个idx而言,可能把step步放到这个结点
        for step in range(n+1, 0,-1):
            # 对这step步而言,可以是向下走,也可以向叶子走
            for leaves in range(0,step,1):
                ans[idx][step] = max(ans[idx][step], ans[idx][step-leaves]+ans[nxt][leaves])
dfs(0)
print(ans[0][n+1])