聚会的快乐

题目描述
你要组织一个由你公司的人参加的聚会。你希望聚会非常愉快,尽可能多地找些有趣的热闹。但是劝你不要同时邀请某个人和他的上司,因为这可能带来争吵。给定N个人(姓名,他幽默的系数,以及他上司的名字),编程找到能使幽默系数和最大的若干个人。
输入输出格式
输入格式:
第一行一个整数N(N<100)。接下来有N行,每一行描述一个人的信息,信息之间用空格隔开。姓名是长度不超过20的字符串,幽默系数是在0到100之间的整数。
输出格式:
所邀请的人最大的幽默系数和。
输入输出样例
输入样例#15
BART 1 HOMER
HOMER 2 MONTGOMERY
MONTGOMERY 1 NOBODY
LISA 3 HOMER
SMITHERS 4 MONTGOMERY
输出样例#18
题面

明显的树形DP

dp[i][0] 表示i这个点不选的最大值

dp[i][1] 表示i这个点选的最大值

转移:

如果i这个点选择,那么他的直系下属就不可以参加,

dp[i][0]+=dfs(to,0);

如果i这个点不选择选择,那么他的直系下属就可以参加也可以不参加

dp[i][1]+=max(dfs(to,0),dfs(to,1));

记忆化搜索,转移

 1 #include<bits/stdc++.h>
 2 #define ll long long
 3 #define DB double
 4 using namespace std;
 5 int n,dp[110][2],val[110],son[110],t[110][110],rt,ans;
 6 bool vis[110][110];
 7 string na[110],up[110];
 8 int dfs(int i,int j)
 9 {
10     if(vis[i][j]) return dp[i][j];
11     vis[i][j]=true;
12     if(i==0) return 0;
13     if(j==1)//这个人参加聚会
14     {
15         dp[i][j]=val[i];
16         for(int k=1;k<=son[i];++k) dp[i][j]+=dfs(t[i][k],0);
17     }
18     else//人不参加聚会
19     {
20         for(int k=1;k<=son[i];++k)
21         dp[i][j]+=max(dfs(t[i][k],0),dfs(t[i][k],1));
22     }
23     return dp[i][j];
24 }
25 int main()
26 {
27     scanf("%d",&n);
28     for(int i=1;i<=n;++i)
29      cin>>na[i]>>val[i]>>up[i];
30     for(int i=1;i<=n;++i)
31     {
32         bool fg=false;
33         for(int j=1;j<=n;++j)
34         {
35             if(i==j)continue;
36             if(na[j]==up[i])
37             {
38                 fg=true;
39                 t[j][++son[j]]=i;
40                 break;
41             }
42         }
43         if(!fg) rt=i;
44     }
45     ans=dfs(rt,0);
46     ans=max(ans,dfs(rt,1));
47     printf("%d\n",ans);
48     return 0;
49 }
View Code
posted @ 2018-04-15 20:00  月亮茶  阅读(256)  评论(1编辑  收藏  举报