コース選択問題(動的計画法)

転載:C ++ソードはオファーを指します:ツリー型のDPツリーコース選択に依存するナップサック問題

トピック

説明

学校はクレジットシステムを実装しています。各必修科目には一定数の単位があり、対応する選択科目の単位を同時に取得する必要があります。学校はNの選択科目を提供し、各学生がMを選択できるコースの数が与えられます。このMコースを受講して評価に合格した学生は、対応するクレジットを取得します。選択科目の中には、直接受講できるコースもあれば、他のコースに基づいてのみ受講できる基本的な知識が必要なコースもあります。たとえば、「Windowsオペレーティングの基本」の後に「フロントページ」を選択する必要があります。「フロントページ」の前提条件を「Windows操作の基本」と呼びます。各コースには、最大で1つの直接的な前提条件があります。2つのコースにも同じ前提条件がある場合があります。各コースには、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です)であり、2番目の番号はこのコースのクレジットです。クレジットは10を超えない正の整数です。

出力

1行目:数字は1つだけです。つまり、実際に選択したコースの単位の総数です。

01ナップサック問題に類似したツリーdp:

#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