动态规划:P2014[CTSC1997] 选课 分组背包 树形DP 分组背包

P2014[CTSC1997] 选课 
题目:

 

 思路:

这题思路跟我的动态规划:P2015二叉苹果树 树形DP 分组背包 - 朱朱成 - 博客园 (cnblogs.com) 思路一模一样,唯一有区别的这题是点权,不再是边权,所以我们计算每个结点连的结点数,要把每个结点数sum[i]初始化为1,然后sum[结点]是+=sum[邻接点],其他都一样。

关键DP代码:

 

 

 

完整代码:

 1 #include<iostream>
 2 #include<algorithm>
 3 #include<vector>
 4 #include<cstring>
 5 using namespace std;
 6 const int maxn = 305;
 7 vector<int>linjie[maxn];
 8 int val[maxn];
 9 int n, m, a, b;
10 int dp[maxn][maxn];
11 int sum[maxn];
12 int xuefen[maxn];
13 void dfs(int u)
14 {
15     for (int i = 0; i < linjie[u].size(); ++i)
16     {
17         dfs(linjie[u][i]);
18         sum[u]+=sum[linjie[u][i]];
19         for (int j = min(sum[u], m); j >= 1; --j)
20         {
21             for (int k = 1; k <= min(j, sum[linjie[u][i]]); ++k)
22             {
23                // cout << dp[u][j] << " " << dp[u][j - k] << " "<<dp[linjie[u][i]][k] << endl;
24                 dp[u][j] = max(dp[u][j], dp[u][j - k] + dp[linjie[u][i]][k]);
25                //cout <<u<<","<<j<<":" << dp[u][j] << endl;
26             }
27         }
28     }
29 }
30 int main()
31 {
32     cin >> n >> m;
33     memset(dp, -0x3f, sizeof(dp));
34     dp[0][0] = 0;
35     for (int i = 1; i <= n; ++i)//构建邻接关系
36     {
37         cin >> a >> b;
38         linjie[a].push_back(i);
39         val[i] = b;
40         dp[i][1] = b;
41     }
42     for (int i = 1; i <= n; ++i)
43     {
44         sum[i] = 1;//初始化
45     }
46    // countsum(0);
47     dfs(0);
48     cout << dp[0][m];
49     return 0;
50 }
51 
52 /*
53 4 2
54 0 1
55 0 2
56 1 3
57 1 4
58 */

 

 

 

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