问题:快乐聚会(树和图上的动态规划)
题目描述
某公司中有明确的上下属关系,可以使用有根树表示。现举办聚会,每个人都有一个快乐指数,但是如果一个的上级参加了聚会,那么此人就不会再参加。求此次聚会最大的快乐指数和为多少?
分析
定义状态
其实经过题目的描述,状态已经呼之欲出了,正如大家所见,每个人都会存在一个快乐指数,如果他参加聚会,在此次聚会中他所贡献的快乐指数就为,反之则为0。故我们可以定义状态为,表示员工x参加或者不参加聚会时他与他下属产生的最大快乐指数和。
状态转移
对于每一个员工,分为两种情况:参加与不参加。所以需要分别更新这两种状态的值:
(1)如果该员工参加聚会,则其下属都不会参加聚会,此时产生的最大快乐指数和为
(2)如果该员工不参加聚会,则其下属可以选择是否参加聚会,此时产生的最大快乐指数和为
边界条件
考虑所有的最底层员工,即整棵树中的所有叶子节点,如果不参加聚会,贡献的快乐指数为0();如果参加聚会,贡献的快乐指数为其本身的快乐指数
(),所求的值为。【由此观之,公司的管理层有多么重要,居然都可以控制每个人的快乐。。。。】
求解方法
动态规划
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叉树)
时间复杂度
由于只需要将数组遍历一遍即可得到答案,故产生的时间复杂度为。