1. 程式人生 > >洛谷 P2014 選課

洛谷 P2014 選課

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 namespace
std; 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 選課