algorithm:派对的最大快乐值

题目描述

员工信息的定义如下:

class Employee{
    int happy; // 这名员工可以带来的快乐值
    std::vector<Employee*> next; // 这名员工有哪些直接下级
};

公司的每个员工都符合 Employee 类的描述。整个公司的人员结构可以看作是一棵标准的、 没有环的多叉树。

树的头节点是公司唯一的老板。除老板之外的每个员工都有唯一的直接上级。
叶节点是没有任何下属的基层员工(subordinates列表为空),除基层员工外,每个员工都有一个或多个直接下级。

这个公司现在要办party,你可以决定哪些员工来,哪些员工不来,规则:

  • 如果某个员工来了,那么这个员工的所有直接下级都不能来
  • 派对的整体快乐值是所有到场员工快乐值的累加
  • 你的目标是让派对的整体快乐值尽量大

给定一棵多叉树的头节点boss,请返回派对的最大快乐值。

class Employee{
public:
    int happy; // 这名员工可以带来的快乐值
    std::vector<Employee*> next; // 这名员工有哪些直接下级
};


class Solution {
public:
    int maxHappy(Employee* boss) {

    }
};

题目解析

对于每一个root,它有两种决策:

  • 当前节点来,则它的子节点不能来,即:root.heap + max(子节点不来)
  • 当前节点不来,则它的子节点可以来也可以不来,即: 0 + max(子节点来,子节点不来)

因此,每次都需要从左树和右树中我们都需要 来,不来 的最大快乐值

递归

class Employee{
public:
    int happy; // 这名员工可以带来的快乐值
    std::vector<Employee*> nexts; // 这名员工有哪些直接下级
};

class Solution {
    
    struct Info{
    public:
        int no;
        int yes;
        
        Info(int no, int yes) : no(no), yes(yes){
            
        }
    };
    
    std::shared_ptr<Info>process(Employee* boss){
        if(boss == nullptr){
            return std::make_shared<Info>(0, 0);
        }
        
        int no = 0;
        int yes = boss->happy;
        for(auto next : boss->nexts){
            auto nextInfo = process(next);
            no += std::max(nextInfo->yes, nextInfo->no);
            yes += nextInfo->no;
        }
        return  std::make_shared<Info>(no, yes);
    }

public:
    int maxHappy(Employee* boss) {
        if(boss == nullptr){
            return 0;
        }
        auto allInfo = process(boss);
        return std::max(allInfo->yes, allInfo->no);
    }
};

递归

class Employee{
public:
    int happy; // 这名员工可以带来的快乐值
    std::vector<Employee*> next; // 这名员工有哪些直接下级
};

class Solution {
    // 当前来到的节点叫cur,
    // up表示cur的上级是否来,
    // 该函数含义:
    // 如果up为true,表示在cur上级已经确定来,的情况下,cur整棵树能够提供最大的快乐值是多少?
    // 如果up为false,表示在cur上级已经确定不来,的情况下,cur整棵树能够提供最大的快乐值是多少?
    int process(Employee* cur, bool up){
        if(up){ // 如果cur的上级来的话,cur没得选,只能不来
            int ans = 0;
            for(auto next : cur->next){
                ans += process(next, false);
            }
            return ans;
        }else{  // // 如果cur的上级不来的话,cur可以选,可以来也可以不来
            int p1 = cur->happy, p2 = 0;
            for(auto next : cur->next){
                p1 += process(next, true);
                p2 += process(next, false);
            }
            return std::max(p1, p2);
        }
    }
public:
    int maxHappy(Employee* boss) {
        if(boss == nullptr){
            return 0;
        }
        return process(boss, false);
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值