公司聚会

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

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

 

   分析:求出以每个节点为根节点的子树去或者不去的最大喜欢程度和,以此往上推,本题就是求根节点去或者不去的最大喜欢程度。显然,这具有最优子序列结构。给每个节点增加两个域,select,unsel,select[i]表示i节点去时,以i节点为根的子树的喜欢程度和,unsel[i]表示i节点不去时,所获得的喜欢程度和。

公式如下:

r.select=r.data+sum(unsel[j]);//j为r的孩子,r.data为节点r的喜欢程度

r.unsel=sum(max{unsel[j],select[j]});
     当i选择去时,它的孩子节点肯定不能去;当i不去时,其孩子节点可以选择去或者不去;然后根据求出的根节点的最大喜欢程度和,找出参加的名单。首先是计算每个节点为根的子树的最大喜欢程度和。
// gongsujuhui.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include<iostream>
#include<stack>
#include<queue>
using namespace std;

typedef struct TreeNode *Position;
typedef struct TreeNode *Tree;

struct TreeNode {
	int love;//喜欢聚会的程度
	Position parent, leftChild, rsibling;
	int select, unselect;        //去或不去以该节点为根的子树的喜欢程度
	bool go;
};

Tree initTree(int love[],int n)             //初始化公司树,15个节点的二叉树,n是人数,love是喜欢程度
{
	Tree T = (Tree)malloc(sizeof(TreeNode));
	T->love = love[1];
	T->parent = NULL;
	T->rsibling = NULL;
	T->go = true;
	T->select = 0;
	T->unselect = 0;
	queue<Position> que;
	que.push(T);
	for (int i = 2; i <= n; i+=2)
	{
		Position pLeft = (Position)malloc(sizeof(TreeNode));
		Position pRight = (Position)malloc(sizeof(TreeNode));
		que.front()->leftChild = pLeft;
		pLeft->love = love[i];
		pRight->love = love[i + 1];
		pLeft->parent = pRight->parent=que.front();
		que.pop();
		pLeft->rsibling = pRight;
		pLeft->leftChild = NULL;
		pRight->leftChild = NULL;
		pRight->rsibling = NULL;
		pLeft->go = pRight->go = true;
		pLeft->select = pLeft->unselect = pRight->select = pRight->unselect = 0;
		que.push(pLeft);
		que.push(pRight);
	}
	return T;
}

void print(Tree T)               //打印公司树
{
	Position left, right;
	queue<Position> que;
	que.push(T);
	while (!que.empty())
	{
		if(que.front()->go)cout << que.front()->love<<'\t';
		left = que.front()->leftChild;
		que.pop();
		if (left != NULL)
		{
			right = left->rsibling;
			que.push(left);
			if (right != NULL)
			{
				que.push(right);
			}

		}
	}
	cout << endl;
}

int sumUnselectSon(Position p)
{
	Position left = p->leftChild;
	int sum = left->unselect;
	while (left->rsibling!=NULL)
	{
		left = left->rsibling;
		sum += left->unselect;
	}
	return sum;
}

int sumMaxson(Position p)
{
	Position left = p->leftChild;
	int sum = left->select > left->unselect ? left->select : left->unselect;
	while (left->rsibling != NULL)
	{
		left = left->rsibling;
		sum += left->select > left->unselect ? left->select : left->unselect;
	}
	return sum;
}


void peopleSelect(Tree T)
{
	stack<Position> sta;
	Position p ;
	p = T;
	while (!sta.empty()||p!=NULL)
	{
		if(p!=NULL)
		{ 
		sta.push(p);
		while (p->leftChild!=NULL)
		{
			p = p->leftChild;
			sta.push(p);
		}
		}
		p=sta.top();
		sta.pop();

		if (p->leftChild == NULL)
		{
			p->select = p->love;
			p->unselect = 0;
		}
		else
		{
			p->select = p->love + sumUnselectSon(p);
			p->unselect = sumMaxson(p);
		}

		p = p->rsibling;
	}
}

void PeopleList(Tree T)
{
	Position r, s;
	r = T;
	if (r == NULL) return;
	else if (r->parent == NULL) {
		if (r->select > r->unselect)
			r->go = 1;
		else
			r->go = 0;
	}
	else
	{
		if (r->parent->go)
			r->go = false;
		else {
			if(r->select > r->unselect)
				r->go = 1;
			else
				r->go = 0;
		}
	}
	if (r->leftChild)
	{
		r = r->leftChild;
		s = r->rsibling;
		PeopleList(r);
		PeopleList(s);
	}
}
int main()
{
	int love[] = { 0,2,5,3,4,8,6,7,17,9,10,16,12,8,3,15 };
	Tree T = initTree(love, 15);
	print(T);
	peopleSelect(T);
	PeopleList(T);
	print(T);
	while (1);
    return 0;
}

  

 
posted @ 2017-04-01 23:41  lineaar  阅读(345)  评论(0编辑  收藏  举报