题目
公司A有n个员工,数组happy表示n个员工产生快乐的分数,二维数组children表示公司的组织架构,children[i,j]=1代表i是j的直属上司。人事部门要举行一个聚会,为使聚会有愉悦的气氛,员工和其直属上司不会同时参加。请问怎么安排聚会名单,使聚会的快乐分数总和最大。
输入:
happy=[3,7,1,4,6,8,9,10,5,4,2,12,3,6]
children=
[[0,1,1,1,0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,1,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,1,1,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,1,1,1,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0,1,1,0,0],
[0,0,0,0,0,0,0,0,0,0,0,0,1,1],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0]
]
输出:
54
思路
定义dp[i]表示以第i个顶点为根的树,其最大的快乐分数。因为有员工和直属上司不能同时参加的限制,所以分两种情况:树根参加或不参加。树根参加,则树根的直接子孩子不参加,而树根的孙子参加。树根不参加,所有孩子参加。比较这两种情况,较大者为dp[i]的值。
代码
#include <vector>
using namespace std;
class CompanyParty {
vector<int> dp;
public:
int settleCompanyParty(vector<int> happy, vector<vector<int>> children) {
dp.resize(happy.size());
getSum(0, happy, children);
return dp[0];
}
void getSum(int node, vector<int> happy, vector<vector<int>> children) {
//看node是不是叶子结点,如果是,则
bool isleaf = true;
for(int i = 0;i < children.size();i++) {
if (children[node][i] == 1) {
getSum(i, happy, children);
isleaf = false;
}
}
if (isleaf) {
dp[node] = happy[node];
}
else {
int sum1 = 0;//node不参加
int sum2 = happy[node];//node参加
for(int i = 0;i < children.size();i++) {
if (children[node][i] == 1) {
sum1 += dp[i];
for(int j = 0;j < children.size();j++) {
if (children[i][j] == 1) {
sum2 += dp[j];
}
}
}
}
if (sum1 > sum2) {
dp[node] = sum1;
}
else {
dp[node] = sum2;
}
}
}
};