动态规划:P1352没有上司的舞会

没有上司的舞会
题目:

 

 思路:

可以学习像区间dp里面,分左右端点dpdp一样,构建二维DP数组,第二维代表有没有连下一个结点,0代表连了下一个结点,1代表没有连,所以我们初始化所有叶子结点的dp[叶子][0]等于叶子的快乐指数,然后从根往下dfs,因为一开始不知道根,和叶子,可以计算出度和入度,然后遍历找到入度为0的点就是根开始dfs,搜到最底层,如果出度为0就是叶子,初始化叶子结点的dp[叶子][0]等于他的快乐指数,否则定义sum1来计算要自己这个结点 sum2来计算不要自己这个结点,显然要自己这个结点就不能要下一个节点了,所以sum1就要加上所有邻接点的dp[邻接点][1],sum2就是0了 。这里注意两个问题 ①:快乐指数可以能是负数,所以sum并不是加上所有邻接点的dp 而是加上每一个邻接点的max(dp,0),如果小于0就不加了。②:初始化问题:sum2初始化为0 不要这个结点,sum1并不是初始化为这个结点的快乐指数,而是初始化为max(0,happy[this]),为什么呢,因为自己这个点的快乐指数小于0还不如不要自己这个点,也不影响别的点的计算,如果少了这行代码就只有90分。

 

关键DP代码:

 

 

 

最优ans就是遍历以每一个结点为起始的1 和 0 要遍历。

遍历代码:

 

 

计算入度和出度及邻接矩阵的构建:

 

 

总AC代码:

 

 1 #include<iostream>
 2 #include<algorithm>
 3 #include<vector>
 4 using namespace std;
 5 const int maxn = 6 * 1e3 + 5;
 6 vector<int>c[maxn];//邻接矩阵
 7 int happy[maxn];
 8 int dp[maxn][2];
 9 int in[maxn];
10 int out[maxn];
11 void dfs(int u)
12 {
13     if (!out[u])
14     {
15         dp[u][0] = happy[u];
16         return;
17     }
18     int sum1 =max( happy[u],0);//如果自己的快乐指数是负的 就直接不邀请自己 也不影响邀请其他的
19     int sum2 = 0;
20     for (int i = 0; i < c[u].size(); ++i)
21     {
22         dfs(c[u][i]);
23         sum1 += max(0,dp[c[u][i]][1]);//如果子树的快乐指数和小于0 就不邀请这个子树的了
24         sum2 += max(0, dp[c[u][i]][0]);//如果子树的快乐指数和小于0 就不邀请这个子树的了
25     }
26     dp[u][0] = sum1;
27     dp[u][1] = sum2;
28     //cout << dp[u][0] << endl;
29     //cout << dp[u][1] << endl;
30 }
31 int n, a, b;
32 int main()
33 {
34     cin >> n;
35     for (int i = 1; i <= n; ++i)
36         cin >> happy[i];
37     for (int i = 1; i < n; ++i)//邻接矩阵的构建
38     {
39         cin >> a >> b;//有向边 b->a
40         c[b].push_back(a);
41         in[a]++;//入度和出度很重要!
42         //cout <<"in" << a << in[a] << endl;
43         out[b]++;
44         //cout << "out" << b << out[b] << endl;
45     }
46     int root;
47     for (int i = 1; i <= n; ++i)
48     {
49         if (!in[i])
50         {
51             root = i;
52             break;
53         }
54     }
55     dfs(root);
56     int ans = -0x7fffffff;
57     for (int i = 1; i <= n; ++i)
58     {
59         ans = max(ans, max(dp[i][0], dp[i][1]));
60     }
61     cout << ans;
62     return 0;
63 }

 

 

通过图:

 

 

 

 

 

 

posted @ 2022-05-03 11:04  朱朱成  阅读(137)  评论(0编辑  收藏  举报