我是靠谱客的博主 个性香菇,最近开发中收集的这篇文章主要介绍选课-背包类树形DP一、题目二、分析三、代码,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

一、题目

选课-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一、题目二、分析三、代码所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(42)

评论列表共有 0 条评论

立即
投稿
返回
顶部