题目大意:有N门功课,每门课有个学分,每门课有一门或没有直接先修课(若课程a是课程b的先修课即只有学完了课程a,才能学习课程b)。一个学生要从这些课程里选择M门课程学习,问他能获得的最大学分是多少?

对于每个节点u,定义u->DP[j]为在剩余课程数为j,以u为根的子树中能够获得的最高学分,则u->DP[j]=max{sum{v->DP[k] | sum[k]==j-1}|v∈u->Son}。

当u的子节点的子节点的DP值通过递归得出后,我们可以对u的每个DP[j]做一个背包。sum[k]==j-1提醒我们背包体积为j-1,k为物体的容量。DP求和提示我们DP[k]作为物体的价值。因为凑成j-1时每个v只选出一个v->DP[k],这提示我们背包按照子节点进行分组,物体最多选一个。这便是一个分组背包!之后将u->DP[j]=u->DP[j-1]+u->score.

注意:

  • 分组背包的初值设置不要忘,DP[0]=0,其余为负无穷。
  • 枚举k时要倒序循环,因为要考虑到物品的体积可能为0,如果正序循环,0最后处理,此时的DP[j]已经是更改后的值。
  • DP[j]=DP[j-1]+score,而不是DP[j]=DP[j]+score
    #include <cstdio>
    #include <cstring>
    #include <vector>
    #include <algorithm>
    #include <cstdarg>
    using namespace std; const int MAX_NODE = 310, MAX_V = MAX_NODE;
    int totV, totNode; struct Node
    {
    int DP[MAX_V];
    int Score;
    int Id;
    vector<Node*> Next;
    }_nodes[MAX_NODE]; void AddEdge(int uId, int vId, int vScore)
    {
    Node *u = uId + _nodes, *v = vId + _nodes;
    u->Id = uId;
    v->Id = vId;
    v->Score = vScore;
    u->Next.push_back(v);
    } void Dfs(Node *cur)
    {
    memset(cur->DP, 0xcf, sizeof(cur->DP));
    cur->DP[0] = 0;
    int sonCnt = cur->Next.size();
    for (int i = 0; i < sonCnt; i++)
    Dfs(cur->Next[i]);
    for (int son = 0; son < sonCnt; son++)
    for (int j = totV; j >= 0; j--)
    for (int k = j; k >= 0; k--)
    cur->DP[j] = max(cur->DP[j], cur->DP[j - k] + cur->Next[son]->DP[k]);
    if(cur!=_nodes)
    for (int j = totV; j > 0; j--)
    cur->DP[j] = cur->DP[j - 1] + cur->Score;
    } int Proceed()
    {
    Node *root = _nodes;
    Dfs(root);
    return root->DP[totV];
    } int main()
    {
    #ifdef _DEBUG
    freopen("c:\\noi\\source\\input.txt", "r", stdin);
    #endif
    memset(_nodes, 0, sizeof(_nodes));
    int u, score;
    scanf("%d%d", &totNode, &totV);
    for (int i = 1; i <= totNode; i++)
    {
    scanf("%d%d", &u, &score);
    AddEdge(u, i, score);
    }
    printf("%d\n", Proceed());
    return 0;
    }

      

luogu2014 选课 背包类树形DP的更多相关文章

  1. [Luogu2014]选课(树形dp)

    [Luogu2014]选课 题目描述 在大学里每个学生,为了达到一定的学分,必须从很多课程里选择一些课程来学习,在课程里有些课程必须在某些课程之前学习,如高等数学总是在其它课程之前学习.现在有N门功课 ...

  2. 洛谷$2014$ 选课 背包类树形$DP$

    luogu Sol 阶段和状态都是树形DP板子题,这里只讲一下背包的部分(转移)叭 它其实是一个分组背包模型,具体理解如下: 对于一个结点x,它由它的子结点y转移而来 在子结点y为根的树中可以选不同数 ...

  3. CH5402 选课【树形DP】【背包】

    5402 选课 0x50「动态规划」例题 描述 学校实行学分制.每门的必修课都有固定的学分,同时还必须获得相应的选修课程学分.学校开设了 N(N≤300) 门的选修课程,每个学生可选课程的数量 M 是 ...

  4. joyOI 选课 【树形dp + 背包dp】

    题目链接 选课 题解 基础背包树形dp #include<iostream> #include<cstdio> #include<cmath> #include&l ...

  5. C++ 洛谷 2014 选课 from_树形DP

    洛谷 2014 选课 没学树形DP的,看一下. 首先要学会多叉树转二叉树. 树有很多种,二叉树是一种人人喜欢的数据结构,简单而且规则.但一般来说,树形动规的题目很少出现二叉树,因此将多叉树转成二叉树就 ...

  6. POJ3345 Bribing FIPA 【背包类树形dp】

    题目链接 POJ 题解 背包树形dp板题 就是读入有点无聊,浪费了很多青春 #include<iostream> #include<cstdio> #include<cm ...

  7. CTSC1998 选课(背包类树形Dp)

    题意: 给出 n 节课的先修课号以及学分(先修课号指的是在学习某节课时先需要学习的课程),求学 m 节课的最大学分. 细节: 1.对于课程 a 其先修课号为 b ,对于课程 b 其先修课号为 c ,则 ...

  8. codevs 1378 选课 (树形DP)

    #include<iostream> #include<cstdio> #include<cstring> using namespace std; ][],f[] ...

  9. 选课(树形DP)

    题目描述 在大学里每个学生,为了达到一定的学分,必须从很多课程里选择一些课程来学习,在课程里有些课程必须在某些课程之前学习,如高等数学总是在其它课程之前学习.现在有N门功课,每门课有个学分,每门课有一 ...

随机推荐

  1. 阿里云 CentOS 6.5 使用XAMPP 搭建LAMP环境

    LAMP环境是常见的服务器环境,也是PHP网站常用的服务器环境,很多人喜欢手动配置,但是手动配置LAMP复杂.麻烦,简单一点的话可以使用集成环境.试了下LNMP的集成环境,用不习惯,另外由于本地一直使 ...

  2. C#比较两个日期的大小 .net

    using System;using System.Collections; public class MyClass{public static void Main(){DateTime dt1 = ...

  3. iOS多线程——GCD篇

    什么是GCD GCD是苹果对多线程编程做的一套新的抽象基于C语言层的API,结合Block简化了多线程的操作,使得我们对线程操作能够更加的安全高效. 在GCD出现之前Cocoa框架提供了NSObjec ...

  4. Leetcode0037--Sudoku Solver 数独游戏

    [转载请注明]http://www.cnblogs.com/igoslly/p/8719622.html 来看一下题目: Write a program to solve a Sudoku puzzl ...

  5. MyEclipse获取注册码

    最近刚装上MyEclipse,一直弹窗提示注册码过期,开始还能接受,到最后,每发布一个项目便弹窗提醒,顿时感觉烦了,得治理治理这个烦人的注册码,下面是一段自动生成注册名和注册码的代码,只需要直接拿来用 ...

  6. jQuery顺序加载图片(初版)

    浏览器加载图片区别: IE:同时加载与渲染 其他:加载完之后再渲染 根据这个差异用jQuery做个实例:按顺序加载一组图片,加载完成后提示. <!DOCTYPE html> <htm ...

  7. [Advanced Algorithm] - Exact Change

    题目 设计一个收银程序 checkCashRegister(),其把购买价格(price)作为第一个参数 , 付款金额 (cash)作为第二个参数, 和收银机中零钱 (cid) 作为第三个参数. ci ...

  8. linux 下取进程占用 cpu/内存 最高的前10个进程

    linux下获取占用CPU资源最多的10个进程,可以使用如下命令组合: ;|head linux下获取占用内存资源最多的10个进程,可以使用如下命令组合: ;|head 命令组合解析(针对CPU的,M ...

  9. Django F查询Q查询Only与Defel

    F/Q查询 测试表 from django.db import models # Create your models here. class MyCharField(models.Field): d ...

  10. PAT_A1150#Travelling Salesman Problem

    Source: PAT A1150 Travelling Salesman Problem (25 分) Description: The "travelling salesman prob ...