选课问题 (动态规划)

转载:C++剑指offer:树形DP之树上的有依赖性的背包问题——选课

题目

描述

学校实行学分制。每门的必修课都有固定的学分,同时还必须获得相应的选修课程学分。 学校开设了 N 门的选修课程,每个学生可选课程的数量 M 是给定的。学生选修了这M门课并考核通过就能获得相应的学分。 在选修课程中,有些课程可以直接选修,有些课程需要一定的基础知识,必须在选了其它的一些课程的基础上才能选修。例如《Frontpage》必须在选修了《Windows 操作基础》之后才能选修。我们称《Windows 操作基础》是《Frontpage》的先修课。每门课的直接先修课最多只有一门。两门课也可能存在相同的先修课。每门课都有一个课号,依次为1,2,3,…。例如:

 

表中 1 是 2 的先修课,2 是 3、4 的先修课。如果要选 3,那么 1 和 2 都一定已被选修过。 你的任务是为自己确定一个选课方案,使得你能得到的学分最多,并且必须满足先修课优先的原则。假定课程之间不存在时间上的冲突。

输入

第1行:2个空格分开的整数 N、M,其中 1≤N≤300,1≤M≤N。

接下来N 行每行代表一门课。课号依次为1,2,…,N。每行有2个空格分开的整数,第一个数为这门课先修课的课号(若不存在先修课则该项为 0),第二个数为这门课的学分。 学分是不超过10 的正整数。

输出

第1行:只有一个数,即实际所选课程的学分总数。

树状dp,与01背包问题相似:

#include<iostream>
#include<iomanip>
#include<vector>
#define N 310
using namespace std;

vector<int>G[N + 1];
vector<vector<int>>dp(N, vector<int>(N, 0));

void dfs(int father, int m)
{
	if (G[father].size() == 0)
		return;
	int son=0;
	for (int i = 0; i < G[father].size(); i++)
	{
		son = G[father][i];
		dfs(son, m);

	for (int i = m + 1; i >=1; i--)
	{
		for (int j = 1; j < i; j++)
			dp[father][i] = max(dp[father][i], dp[son][j] + dp[father][i - j]);
	}

	}
}
void visit()
{
	for (int i = 0; i < 10; i++)
	{
		for (int j = 0; j <10; j++)
		{
			cout << setw(5)<<dp[i][j];
		}
		cout << endl;
	}

}
int main()
{
	int n, m;
	while (cin >> n >> m)
	{
		for (int i = 1; i <= n; i++)
		{
			int father, score;
			cin >> father >> score;
			G[father].push_back(i);
			dp[i][1] = score;
		}
		visit();

		dfs(0, m);
		cout << dp[0][m + 1] << endl;
		visit();


	}
	return 0;
}
/*
7 4
2 2
0 1
0 4
2 1
7 1
7 6
2 2
*/

猜你喜欢

转载自blog.csdn.net/weixin_40823740/article/details/109400117