算法复习之动态规划(7)

问题:快乐聚会(树和图上的动态规划)

题目描述

        某公司中有明确的上下属关系,可以使用有根树表示。现举办聚会,每个人都有一个快乐指数a_i,但是如果一个的上级参加了聚会,那么此人就不会再参加。求此次聚会最大的快乐指数和为多少?

分析

定义状态

        其实经过题目的描述,状态已经呼之欲出了,正如大家所见,每个人都会存在一个快乐指数,如果他参加聚会,在此次聚会中他所贡献的快乐指数就为a_i,反之则为0。故我们可以定义状态为f(x,1/0),表示员工x参加或者不参加聚会时他与他下属产生的最大快乐指数和。

状态转移

        对于每一个员工,分为两种情况:参加与不参加。所以需要分别更新这两种状态的值:

        (1)如果该员工参加聚会,则其下属都不会参加聚会,此时产生的最大快乐指数和为

f(x,1)=a_x+\sum_{y\in S(x)}f(y,0) 

        (2)如果该员工不参加聚会,则其下属可以选择是否参加聚会,此时产生的最大快乐指数和为

f(x,0)=\sum_{y\in S(x)}{max\left \{ f(y,0),f(y,1) \right \}} 

边界条件

         考虑所有的最底层员工,即整棵树中的所有叶子节点,如果不参加聚会,贡献的快乐指数为0(f(leaf,0)=0);如果参加聚会,贡献的快乐指数为其本身的快乐指数

f(leaf,1)=a_{leaf}),所求的值为max\left \{ f(root,0),f(root,1) \right \}。【由此观之,公司的管理层有多么重要,居然都可以控制每个人的快乐。。。。】

求解方法

动态规划

struct TreeNode {
    int happyValue = 0;
    vector<int> childList;
};

vector<int> happyParty(vector<TreeNode>& company, int root) {
    int candiHappy = company[root].happyValue;
    int uncandiHappy = 0;
    for (const auto& child: company[root].childList){
        vector<int> childRes = happyParty(company, child);
        candiHappy += childRes[1];
        uncandiHappy += max(childRes[0], childRes[1]);
    }
    vector<int> res = { candiHappy, uncandiHappy };
    return res;
}

        使用树形dp的思想遍历更新整个公司内部两种情况下的最大快乐值。(我使用近似树的结构体,放在数组里维护了,如果你熟练的话也可以直接写成n叉树)

时间复杂度

        由于只需要将数组遍历一遍即可得到答案,故产生的时间复杂度为O(n)

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小糖豆豆

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值