洛谷 2014 選課 樹形DP 解題報告

題目描述

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

代碼

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<cmath>
#include<vector>
using namespace std;
const int N=300+5;
int m,n,next[N],num=0,head[N],dp[N][N];
void build(int u)
{
    next[++num]=head[u];
    head[u]=num;
}
void work(int x)
{
    for (int i=head[x];i!=-1;i=next[i])
    {
        work(i);
        for (int j=m+1;j>1;j--)
        for (int k=j-1;k>=1;k--)
        dp[x][j]=max(dp[x][j],dp[x][j-k]+dp[i][k]);
    }
}
int main()
{
    scanf("%d%d",&n,&m);
    memset(head,-1,sizeof(head));
    for (int i=1;i<=n;i++)
    {
        int u,v;
        scanf("%d%d",&u,&v);
        dp[i][1]=v;
        build(u);
    }
    work(0);
    printf("%d\n",dp[0][m+1]);
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章