递归算法-派对的最大快乐值,多叉树的递归应用

文章介绍了如何在给定的员工多叉树结构中,通过递归算法找到使派对整体快乐值最大的员工组合。两种递归解法分别从头节点出发,考虑当前员工及其子节点来或不来的情况,通过比较所有可能的组合来确定最大快乐值。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

计算派对最大快乐值

题目描述

1.员工信息的定义如下:

	public class Employee {
		public int happy;
		public List<Employee> nexts;

		public Employee(int h) {
			happy = h;
			nexts = new ArrayList<>();
		}

	}

2.题目描述

公司的每个员工都符合 Employee 类的描述。整个公司的人员结构可以看作是一棵标准的、 没有环的多叉树 树的头节点是公司唯一的老板,除老板之外的每个员工都有唯一的直接上级 叶节点是没有任何下属的基层员工(subordinates列表为空),除基层员工外每个员工都有一个或多个直接下级 这个公司现在要办party,你可以决定哪些员工来,哪些员工不来,
规则:
1.如果某个员工来了,那么这个员工的所有直接下级都不能来
2.派对的整体快乐值是所有到场员工快乐值的累加
3.你的目标是让派对的整体快乐值尽量大 给定一棵多叉树的头节点boss,请返回派对的最大快乐值。

递归解法一.

解题思路:
递归算法就要从头节点考虑,第一个节点可来可不来,两种情况:
1.头节点来了,他的直接子节点,也是可来可不来,两种情况,分别去递归,找出最大的值.
2.头节点来了,.那么他的直接子节点都不能来,然后去递归,
下面我们代码去实现.

	/**
	递归过程 flag 为true 代表来,false 代表不来.
	分别去递归
	*/
	public static int process(Employee cur, boolean flag) {
		if (flag) { // 如果cur的上级来的话,cur没得选,只能不来
			int ans = 0;
			for (Employee next : cur.nexts) {
				ans += process1(next, false);
			}
			return ans;
		} else { // 如果cur的上级不来的话,cur可以选,可以来也可以不来
			int p1 = cur.happy;
			int p2 = 0;
			for (Employee next : cur.nexts) {
				p1 += process1(next, true);
				p2 += process1(next, false);
			}
			return Math.max(p1, p2);
		}
	}
	/**
	* 主方法调用
	*/
public static int maxHappy1(Employee emp) {
		if (emp == null) {
			return 0;
		}
		return process1(emp, false);
	}

递归解法二

把过程分解掉,到每个节点上的来或者不来情况都去递归出结果,然后进行比较

/**
主方法调用
*/
	public static int maxHappy2(Employee head) {
		Info allInfo = process(head);
		return Math.max(allInfo.no, allInfo.yes);
	}

	public static class Info {
		public int no; //不来的情况
		public int yes; //来的情况

		public Info(int n, int y) {
			no = n;
			yes = y;
		}
	}

	public static Info process(Employee x) {
		if (x == null) {
			return new Info(0, 0);
		}
		int no = 0; //不来的话 初始值为0 
		int yes = x.happy; //来的话初始值 是他本身的值
		for (Employee next : x.nexts) {
		//递归
			Info nextInfo = process(next);
			no += Math.max(nextInfo.no, nextInfo.yes);
			yes += nextInfo.no;

		}
		return new Info(no, yes);
	}

二叉树递归算法–最低公共祖先

<think>好的,我现在需要处理用户关于如何根据质量选择物品放入有限容量背包的问题。用户意图是了解物品的质量如何影响选择,以决定放入哪些物品。首先,我需要明确用户的问题核心是背包问题的优化,特别是0/1背包问题,因为物品只能选择放入或不放入。 接下来,我要考虑用户的背景。可能用户对算法不太熟悉,所以需要解释基本概念,同时提供实用的方法。可能需要分步骤说明,比如动态规划、贪心算法和回溯法,但根据用户要求避免使用步骤词汇,所以可能需要用不同的方法作为标题,每个方法下详细说明。 需要确保回答满足格式要求:个方法或步骤,换行分隔,包含代码和公式时正确使用格式。例如,动态规划涉及公式,需要用$$包裹。代码示例要正确标注语言类型,用三个反引号包裹。 然后,检查是否需要网络搜索。虽然我对背包问题有基本了解,但可能需要确认最新的方法或实际应用中的技巧。例如,是否有常见的优化技巧或实际案例。不过,核心方法可能已经足够,动态规划和贪心算法是经典解法。 整合信息时,要确保每个方法的解释清晰,包括时间复杂度、优缺点,帮助用户根据情况选择。例如,动态规划适合精确解但时间成本高,贪心算法适合快速近似,回溯法适合物品数量较少的情况。 在生成回答时,避免第一人称,直接陈述方法。每个方法部分换行,符合用户要求的格式。同时,确保引用内容分散在回答中,而不是集中在末尾。例如,在动态规划部分引用公式,在贪心部分提到价密度,这些都需要正确标注。 最后,生成相关问题部分。需要基于原始问题和回答内容,提出可能的相关问题,比如不同背包问题的变种、实际应用案例或优化技巧。确保三个问题,用正确格式,标题在同一行,无余空格或换行。 现在,检查所有要求是否满足:避免步骤词汇,分方法说明,公式和代码格式正确,相关问题符合规范。确认无误后,整合成最终回答。</think>根据物品质量选择放入有限容量背包的最优方案,需结合背包容量和物品价进行数学建模。以下是三种常用解决方案及其实现方法: **动态规划法** 适用于精确求解,时间复杂度为$O(nW)$(n为物品数量,W为背包容量) 建立二维数组$dp[i][w]$表示前i个物品在容量w时的最大 状态转移方程: $$dp[i][w] = \max(dp[i-1][w], dp[i-1][w-w_i] + v_i)$$ ```python def knapsack(weights, values, capacity): n = len(values) dp = [[0]*(capacity+1) for _ in range(n+1)] for i in range(1, n+1): for w in range(1, capacity+1): if weights[i-1] <= w: dp[i][w] = max(dp[i-1][w], dp[i-1][w-weights[i-1]] + values[i-1]) else: dp[i][w] = dp[i-1][w] return dp[n][capacity] ``` **贪心算法** 时间复杂度$O(n\log n)$,适合快速近似解 按价密度排序(价/质量): $$\rho_i = \frac{v_i}{w_i}$$ 优先选择高密度物品,直到背包装满 **回溯法** 适用于物品数较少的情况(n ≤ 20) 递归遍历所有可能组合,剪枝无效分支 时间复杂度$O(2^n)$,需配合记忆化优化 实际应用建议: - 物品数<20时使用回溯法 - 中等规模(n=50, W=1000)用动态规划 - 大规模问题采用贪心算法+误差补偿
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值