洛谷P2014題解

首先,2014這個題號給人一種很特殊的感覺啊!~~~

昂,由於剛剛學了樹形DP,所以便做了這道題。

(我的意思是若有寫的不好的地方儘量包涵,儘量QwQ~~)

題目描述

在大學裏每個學生,爲了達到一定的學分,必須從很多課程裏選擇一些課程來學習,在課程裏有些課程必須在某些課程之前學習,如高等數學總是在其它課程之前學習。現在有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

f[i][j] 表示第i各節點取第j個兒子時的最max(min)價值

狀態轉移方程

F[i][j]=max/min(f[i][j],f[i][j-k]+f[兒子節點編號][k]=....)

代碼如下:

(由於我也是學的,所以說有和別的相似的不要吐槽了樓~~)

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
const int maxn = 2018 ;
int n , m , f[maxn][maxn] ;
int head[maxn] , next[maxn] , w[maxn] ;//head[],next[]數組模擬鄰接表,w[]用來存邊權
int dfs(int x){
	int sum = 0 ;
	for(int i = head[x] ; i != -1 ; i = next[i])//這裏就類似於一個揹包了!!
	{
		int t = dfs(i) ;
		sum += t + 1 ;
		for(int j = sum ; j >= 0 ; j --)
		for(int k = 0 ; k <= t ; k ++)
		if(j - k - 1 >= 0) f[x][j] = max(f[x][j] , f[x][j-k-1] + f[i][k]) ;//狀態轉移方程上面有講
	}
	return sum ; 
}
int main(){
	scanf("%d%d",&n,&m) ;//輸入點數,選擇的個數
	memset(head,-1,sizeof(head)) ;
//用鏈性表來儲存
	for(int i = 1 ; i <= n ; i ++)
	{
		int x ;
		scanf("%d%d",&x,&w[i]) ;//存一棵樹,不多解釋
		next[i] = head[x] ;
		head[x] = i ;
	}
	for(int i = 1 ; i <= n ; i ++) f[i][0] = w[i] ;
	dfs(0);
	printf("%d\n",f[0][m]) ;
	return 0 ;
} 

相似題目鏈接

有線電視網

聚會的快樂

二叉蘋果樹

二叉蘋果樹題解

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章