概述
一、题目
选课-AcWing286
二、分析
由题目给定的数据进行建树将得到诸多颗树,即森林。此时我们可以添加节点0,设所有不需要先修课的课程先修课为0(有点绕0.0)。这样就得到一颗树,这将利于后面数据的处理。
1、定义dp数组:
从以i为根节点的子树选择j个课程,可获得的最大学分为dp[i][j]
2、注意方程:
d[i][j] = max(dp[i][j],dp[i][k]+dp[y][j-k])
其中i为y的父节点,1<=k<=m
3、目标
dp[0][m]
三、代码
#include <bits/stdc++.h>
using namespace std;
const int N = 310;
int h[N], e[N * 2], ne[N * 2], idx;
int w[N];
int n, m;
int
dp[N][N];
bool st[N];
void add(int a, int b)
{
e[idx] = b;
ne[idx] = h[a];
h[a] = idx++;
}
void dfs(int root)
{
dp[root][1] = w[root];
for (int i = h[root]; i != -1; i = ne[i])
{
int y = e[i];
if (!st[y])
{
st[y] = true;
dfs(y);
for (int j = m; j >= 2;j--)
{
for (int k = 1; k < m;k++)
{
if(dp[y][j-k]>0)
dp[root][j] = max(dp[root][j], dp[root][k] + dp[y][j - k]);
}
}
st[y] = false;
}
}
}
int main()
{
cin >> n >> m;
for (int i = 0; i <= n; i++)
{
h[i] = -1;
}
memset(dp, 0x8f, sizeof dp);
for (int i = 1; i <= n; i++)
{
int a, b;
cin >> a >> b;
add(i, a), add(a, i);
w[i] = b;
}
m++;
st[0] = true;
dfs(0);
cout << dp[0][m] << endl;
return 0;
}
最后
以上就是个性香菇为你收集整理的选课-背包类树形DP一、题目二、分析三、代码的全部内容,希望文章能够帮你解决选课-背包类树形DP一、题目二、分析三、代码所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复