动态规划: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 */