云淡风轻
Stay foolish,stay hungry.

Stewart教授是一家公司总裁的顾问,这家公司计划一个公司聚会。这个公司有一个层次式的结构;也就是说,管理关系形成一棵以总裁为根的树。人事部给每个雇员以喜欢聚会的程度来排名,这是个实数。为了使每个参加者都喜欢这个聚会,总裁不希望一个雇员和他(她)的直接上司同时参加。

Stewart教授面对一棵描述公司结构的树,使用了左子女、右兄弟表示法。树中每个结点除了包含指针,还包含雇员的名字和该雇员喜欢聚会的排名。描述一个算法,它生成一张客人列表,使得客人喜欢聚会的程度的总和最大。分析你的算法的执行时间。

解答:这题目很像背包问题中的依赖背包问题,公司的每个成员都有去或不去两个状态,我们0表示去,1表示不去,而每个状态的选择又会影响到它孩子节点的状态,假设公司员工的树图符合下面这个图:

计划一个公司聚会 - kevinlee_2010 - 云淡风轻
 我们用R[N]表示以N为根节点的子树参加聚会的喜好程度的最大值,用L[N]表示节点N对参加聚会的喜好程度。那么我们知道R[N]就是以下两个值得最大值:
R[N.1]=L[N]+∑ R[N.children.0]    表示节点N参加聚会,那么它所有的孩子都不能参加
R[N.0]=∑ max{R[N.children.1],R[N.children.0]}    表示节点N不参加聚会,那么它所有的孩子可以参加也可以不参加
于是R[N]=max{R[N.1],R[N.0]},哪个值大,就知道了N应不应该去。
在实现过程中我们可以从根节点开始递归遍历一下树,求出其每个节点的R[N.0]和R[N.1],递归结束的条件为到达叶节点N时R[N.0]=0,R[N.1]=L[N],在求出每个节点的R[N.0]和R[N.1]之后,我们递归再遍历一次树,来决定每个节点要不要参加聚会,对于每个内部节点,
如果它没有父节点(也就是根节点)那么设置R[N.0]>R[N.1]?N.state=0:N.state=1
如果是非根节点,首先判断if parent[N].state=1,  N.state=0    父节点去,孩子都不能去

                       else R[N.0]>R[N.1]?N.state=0:N.state=1  父节点去,孩子可去可不去

然后对每个N如果有孩子,则递归地遍历他每一个孩子。因为总的时间为两次遍历的时间O(2n)

代码后面会附上,to be continued....


posted on 2011-12-07 22:49  kevin Lee  阅读(900)  评论(0编辑  收藏  举报