洛谷P2014 選課

2022-03-17 17:06:44 字數 3107 閱讀 4048

題目描述

在大學裡每個學生,為了達到一定的學分,必須從很多課程裡選擇一些課程來學習,在課程裡有些課程必須在某些課程之前學習,如高等數學總是在其它課程之前學習。現在有n門功課,每門課有個學分,每門課有一門或沒有直接先修課(若課程a是課程b的先修課即只有學完了課程a,才能學習課程b)。乙個學生要從這些課程裡選擇m門課程學習,問他能獲得的最大學分是多少?

輸入輸出格式

輸入格式:

第一行有兩個整數n,m用空格隔開。(1<=n<=300,1<=m<=300)

接下來的n行,第i+1行包含兩個整數ki和si, ki表示第i門課的直接先修課,si表示第i門課的學分。若ki=0表示沒有直接先修課(1<=ki<=n, 1<=si<=20)。

輸出格式:

只有一行,選m門課程的最大得分。

輸入輸出樣例

輸入樣例#1

7  4

2  2

0  1

0  4

2  1

7  1

7  6

2  2

輸出樣例#1

13演算法:

樹形dp

分析:

這道題一拿起來就感覺它好像是乙個揹包問題。但其實普通的有依賴性揹包問題是無法解決這種有互相依賴的像圖一樣的問題,然而我們又發現先修課和後續課存在著關聯,於是我們就可以用樹形dp。

假如按照之前套路走,我們應該構建一棵多叉樹,在這棵樹上進行動規。嗯,沒問題。

但是,第一資料範圍可能會卡掉幾個點,第二,**量會非常大,而且狀態轉移很難寫。

那麼我們用圖論的方法吧!

嗯,沒問題。

但是請想想圖論的演算法解決這道題又有點殺雞用牛刀了。而且碼量絕對不小。

那麼,我們可以用多叉樹轉二叉樹的思想來解決這個問題。

怎麼轉呢?

先想乙個問題,在一棵多叉樹中,兄弟的兄弟還是兄弟,兒子的兄弟也還是自己的兒子。兄弟的兒子就與自己沒什麼關聯。

那麼我們通過這個性質,構造一棵二叉樹,令其滿足任意一棵子樹的根節點的非空左兒子是自己原來的兒子,非空右兒子是自己原來的兄弟。那麼一棵樹就建好了。

然後,想狀態轉移方程。自己的兄弟是和自己有同等的發展機遇的,所以根節點能經歷的事,能分到的課程數,它現在的右兒子(兄弟)也同樣能經歷。所以也要先遍歷。

至於兒子,可以兒子和兄弟一起分課程,那麼一起去兩個兒子也是可行的。

那麼我們得到以下方程:f[root][len]=max(f[root][len],max(f[b[root]][len],f[b[root]][i]+f[c[root]][len-i-1]+w[root]));

設f[root][len]表示以root為根節點的時候取len門課程可以取得的最大收益。那麼狀態轉移的狀態就有完全不變、不選根節點(只選兄弟)和孩子兄弟一起分這三種情況,很好理解。

對於儲存,可以選擇鏈式前向星,用存圖的方式來儲存,那麼dfs的時候就有些奇怪。

也可以用類似鍊錶的形式存上一條邊,同樣快捷。

上**:

1 #include2 #include3 #include4 #include5

using

namespace

std;67

int w[310],b[310],c[310],f[310][310],n,m,t; //

w是權值,b是兄弟,c是孩子

89 inline int read() //

讀入優化

1019

20void dfs(int root,int len) //

記憶化21

29int

i;30 dfs(b[root],len); //

兄弟和自己有同等的發展機遇

31for (i=0;i//

兄弟孩子一起分

3237

return;38

}3940int

main()

4155 dfs(c[n+1

],m);

56 printf("

%d",f[c[n+1

]][m]);

57return0;

58 }

總結一點,樹規的dfs很好理解,從哪開始,從哪結束,從哪輸出。

嗯,就這樣了。

洛谷P2014 選課

題目描述 在大學裡每個學生,為了達到一定的學分,必須從很多課程裡選擇一些課程來學習,在課程裡有些課程必須在某些課程之前學習,如高等數學總是在其它課程之前學習。現在有n門功課,每門課有個學分,每門課有一門或沒有直接先修課 若課程a是課程b的先修課即只有學完了課程a,才能學習課程b 乙個學生要從這些課程...

洛谷P2014 選課

又是一道樹型dp,不過這次是以點帶權值,因為根是不確定的,我們可以設個虛根 0 因為算是多了一點,所以總點數應該 因為是點帶權值,所以不用dfs邊的數量了,不過有一點虛注意,因為多了乙個點,所以j層迴圈 所選的邊數 下界應該是到2的。include include using namespace s...

洛谷P2014 選課

在大學裡每個學生,為了達到一定的學分,必須從很多課程裡選擇一些課程來學習,在課程裡有些課程必須在某些課程之前學習,如高等數學總是在其它課程之前學習。現在有n門功課,每門課有個學分,每門課有一門或沒有直接先修課 若課程a是課程b的先修課即只有學完了課程a,才能學習課程b 乙個學生要從這些課程裡選擇m門...