Vijos 1180 選課 樹形dp

2021-07-15 23:55:33 字數 1854 閱讀 7146

p1180選課

描述 學校實行學分制。每門的必修課都有固定的學分,同時還必須獲得相應的選修課程學分。學校開設了n(n<300)門的選修課程,每個學生可選課程的數量m是給定的。學生選修了這m門課並考核通過就能獲得相應的學分。

在選修課程中,有些課程可以直接選修,有些課程需要一定的基礎知識,必須在選了其它的一些課程的基礎上才能選修。例如《frontpage》必須在選修了《windows操作基礎》之後才能選修。我們稱《windows操作基礎》是《frontpage》的先修課。每門課的直接先修課最多只有一門。兩門課也可能存在相同的先修課。每門課都有乙個課號,依次為1,2,3,…。 例如:

表中1是2的先修課,2是3、4的先修課。如果要選3,那麼1和2都一定已被選修過。   你的任務是為自己確定乙個選課方案,使得你能得到的學分最多,並且必須滿足先修課優先的原則。假定課程之間不存在時間上的衝突。

輸入格式

輸入檔案的第一行包括兩個整數n、m(中間用乙個空格隔開)其中1≤n≤300,1≤m≤n。

以下n行每行代表一門課。課號依次為1,2,…,n。每行有兩個數(用乙個空格隔開),第乙個數為這門課先修課的課號(若不存在先修課則該項為0),第二個數為這門課的學分。學分是不超過10的正整數。

輸出格式

輸出檔案每行只有乙個數。第一行是實際所選課程的學分總數。

樣例輸入

7 4

2 2

0 1

0 4

2 1

7 1

7 6

2 2樣例輸出

13典型的多叉轉二叉問題。。

對於這種有兩種表示方法,一種是兄弟兒子表示法,另一種是鍊錶法,類似地設定乙個當前兒子(相當於head),然後用next儲存即可。

轉成二叉之後,依賴關係會改變,那麼就需要在dp的時候處理一下。

dp[u][k] 那麼就表示當前u節點以及其兄弟的樹一共取k個的最大收益。

轉移的時候列舉給兄弟多少個就可以了,注意是記憶化搜尋!

另外如果不轉成二叉, 就是泛化物品的思想,轉化成01揹包來處理每乙個節點。

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#ifdef win32

#define auto "%i64d"

#else

#define auto "%lld"

#endif

using

namespace

std;

#define smax(x,tmp) x=max((x),(tmp))

#define smin(x,tmp) x=min((x),(tmp))

const

int inf=0x3f3f3f3f;

const

int maxn=305;

int son[maxn],bro[maxn],cost[maxn];

int n,m;

int root;

int f[maxn][maxn];

inline

void insert(int u,int fa,int val)

void init()

}int dfs(int u,int k)

int main()

vijos 1180 選課 樹形DP

學校實行學分制。每門的必修課都有固定的學分,同時還必須獲得相應的選修課程學分。學校開設了n n 300 門的選修課程,每個學生可選課程的數量m是給定的。學生選修了這m門課並考核通過就能獲得相應的學分。在選修課程中,有些課程可以直接選修,有些課程需要一定的基礎知識,必須在選了其它的一些課程的基礎上才能...

vijos P1180 選課 樹形dp

多叉的情況不好做,所以可以轉換成二叉樹.那麼設dp i j 為以i為根節點的子樹上選擇j門課.dp i j max dp right j dp left k 1 dp right j k credit i 1 k j 轉移方程時一定要注意右兒子都是兄弟不是兒子 因為轉換成了二叉樹,所以任何節點i的右...

Vijos 題庫 選課 P1180

描述 學校實行學分制。每門的必修課都有固定的學分,同時還必須獲得相應的選修課程學分。學校開設了n n 300 門的選修課程,每個學生可選課程的數量m是給定的。學生選修了這m門課並考核通過就能獲得相應的學分。在選修課程中,有些課程可以直接選修,有些課程需要一定的基礎知識,必須在選了其它的一些課程的基礎...