zoukankan      html  css  js  c++  java
  • Luogu P2014 选课 (树形DP)

    题目

    题目描述

    在大学里每个学生,为了达到一定的学分,必须从很多课程里选择一些课程来学习,在课程里有些课程必须在某些课程之前学习,如高等数学总是在其它课程之前学习。现在有N门功课,每门课有个学分,每门课有一门或没有直接先修课(若课程a是课程b的先修课即只有学完了课程a,才能学习课程b)。一个学生要从这些课程里选择M门课程学习,问他能获得的最大学分是多少?

    输入输出格式

    输入格式:

    第一行有两个整数N,M用空格隔开。(1<=N<=300,1<=M<=300)

    接下来的N行,第i+1行包含两个整数kisi, ki表示第i门课的直接先修课,si表示第i门课的学分。若ki=0表示没有直接先修课(1<=ki<=N, 1<=si<=20)。

    输出格式:

    只有一行,选M门课程的最大得分。

    输入输出样例

    输入样例:
    7  4
    2  2
    0  1
    0  4
    2  1
    7  1
    7  6
    2  2
    
    输出样例:
    13
    

    题解

    又是一道经典的树形DP,和二叉苹果树很像,不过用到了背包(Knapsack)的思想

    dp[i][j]表示i课程下选择j门课程得到的最大学分

    代码

    #include <bits/stdc++.h>
    using namespace std;
    struct node {
      int credit, father;
      vector<int> attached;
    } tree[310];
    int n, m;
    int dp[310][310];
    inline int Dfs(const int &now) {
      if (!tree[now].attached.size()) return 0;
      register int sum(0);
      for (register int i(0), 
                        t_size(tree[now].attached.size()), tmp; i < t_size; ++i) {
        sum += tmp = Dfs(tree[now].attached[i]);
        for (register int j(++sum); j; --j) {
          for (register int k(0); k <= tmp; ++k) {
            if (j - k - 1 >= 0) dp[now][j] = max(dp[now][j], 
                                                 dp[now][j - k - 1] + 
                                                 dp[tree[now].attached[i]][k]);
          }
        }
      }
      return sum;
    }
    int main(int argc, char **argv) {
      scanf("%d %d", &n, &m);
      for (register int i(1), attached_to, credit; i <= n; ++i) {
        scanf("%d %d", &attached_to, &credit);
        tree[attached_to].attached.push_back(i);
        tree[i].father = attached_to;
        tree[i].credit = dp[i][0] = credit;
      }
      Dfs(0);
      printf("%d
    ", dp[0][m]);
      return 0;
    }
    
  • 相关阅读:
    [SDOI2009]生日礼物(单调队列)
    [luogu1638]逛画展(单调队列)
    【最短路】·SPFA算法实现
    [UVA10474]大理石在哪儿
    【转载】C++中string erase函数的使用
    【转载】高精度减法的OP写法
    【转载】ST表
    串门赛: NOIP2016模拟赛——By Marvolo 丢脸记
    Bzoj 3813 奇数国 题解 数论+线段树+状压
    Bzoj 2064 分裂 题解
  • 原文地址:https://www.cnblogs.com/forth/p/9537813.html
Copyright © 2011-2022 走看看