zoukankan      html  css  js  c++  java
  • 公司聚会

       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<<'	';
    		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;
    }
    

      

     
  • 相关阅读:
    2018 ACM 网络选拔赛 徐州赛区
    2018 ACM 网络选拔赛 焦作赛区
    2018 ACM 网络选拔赛 沈阳赛区
    poj 2289 网络流 and 二分查找
    poj 2446 二分图最大匹配
    poj 1469 二分图最大匹配
    poj 3249 拓扑排序 and 动态规划
    poj 3687 拓扑排序
    poj 2585 拓扑排序
    poj 1094 拓扑排序
  • 原文地址:https://www.cnblogs.com/linear/p/6657923.html
Copyright © 2011-2022 走看看