洛谷 P2014 選課
阿新 • • 發佈:2017-09-03
article 輸入輸出格式 data blank pla pid 節點 scan class
P2014 選課
題目描述
在大學裏每個學生,為了達到一定的學分,必須從很多課程裏選擇一些課程來學習,在課程裏有些課程必須在某些課程之前學習,如高等數學總是在其它課程之前學習。現在有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[i][j]是以第i個節點為根的二叉子樹中選j門功課所能獲得的最多的學分。
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespacestd; int n,m; int lchild[301],rchild[301]; int w[301],dad[301],f[301][301]; int dfs(int i,int j){ if(i>n||i<1||j>m||j<1) return 0; if(f[i][j]) return f[i][j]; for(int k=0;k<j;k++) f[i][j]=max(f[i][j],dfs(lchild[i],k)+dfs(rchild[i],j-k- 1)+w[i]); f[i][j]=max(f[i][j],dfs(rchild[i],j)); return f[i][j]; } int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) scanf("%d%d",&dad[i],&w[i]); for(int i=1;i<=n;i++){ int fa=dad[i]; if(!lchild[fa]) lchild[fa]=i; else{ fa=lchild[fa]; while(rchild[fa]) fa=rchild[fa]; rchild[fa]=i; } } cout<<dfs(lchild[0],m); }
洛谷 P2014 選課