首页 > 其他分享 >洛谷P2014 [CTSC1997] 选课

洛谷P2014 [CTSC1997] 选课

时间:2022-11-26 20:11:06浏览次数:46  
标签:结点 洛谷 选课 P2014 cnt int 课程 修课 dp

sloj P2006. 「树上背包」选课

题目描述

在大学里每个学生,为了达到一定的学分,必须从很多课程里选择一些课程来学习,在课程里有些课程必须在某些课程之前学习,如高等数学总是在其它课程之前学习。现在有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问题,相信大家都做过了,但估计看到这的人都不会树形dp版会了你还看我干吗,还不去多刷几道 接下来谈正事 树形dp大部分都可以用记忆化搜索做的,相信大家这个都会,我就不多谈了 照例,挑战的原因是想作死 问题解析: 每门课程最多只有 1 门直接先修课,如果我们把课程看成结点,也就是说每个结点最多只一个前驱结点。 如果把前驱结点看成父结点,换句话说,每个结点只有一个父结点。显然具有这种结构的模型是树结构,要么是一棵树,要么是一个森林。 问题就转化: 在一个有 M 个结点的森林中选取 N 个结点,使得所选结点的权值之和最大。同时满足每次选取时,若选儿子结点,必选根结点的条件。 如图 1,为两棵树,我们可以虚拟一个结点,将这些树连接起来,那么森林就转会为了 1 棵树, 选取结点时,从每个儿子出发进行选取。 这样看来这题和上题差不多:从根开始,把 M+1 个机会分配下去。状态也基本一样,f[i,j] 表示以i 为根的子树中选 j 门课能获得的最大学分。 但这题的树不是二叉的,不能像上题一样枚举分配,于是我们尝试将树转为二叉树,采取左儿子右兄弟的转换方法。具体做法参见代码 左儿子右兄弟写了个n2的蒟蒻 放心,代码里是O(n) 那么,不多说了,上代码
#include<bits/stdc++.h>
using namespace std;
struct edge{
    int u,v,w,ne;
}e[100010];
int n,m,h[3010],dp[3010][3010],cnt,son[3010];
void add(int u,int v,int w){
    cnt++;
    e[cnt].u = u;
    e[cnt].v = v;
    e[cnt].w = w;
    e[cnt].ne = h[u];
    h[u] = cnt;
}
void f(int x){
    for(int i = h[x];i;i = e[i].ne){
        f(e[i].v);
        son[x]+=son[e[i].v];
        for(int j = son[x];j;j--)
            for(int k = 1;k<=son[e[i].v]&&k<=j;k++)
                dp[x][j] = max(dp[x][j],dp[x][j-k]+dp[e[i].v][k]-e[i].w);
    }
}
int main(){
    scanf("%d%d",&n,&m);
    for(int i = 1;i<=n-m;i++){
        int k,x,y;
        scanf("%d",&k);
        for(int j = 1;j<=k;j++){
            scanf("%d%d",&x,&y);
            add(i,x,y);
        }
    }
    memset(dp,128,sizeof(dp));
    for(int i = n-m+1;i<=n;i++){
        int x;
        scanf("%d",&x);
        son[i] = 1;
        dp[i][1] = x;
    }
    for(int i = 1;i<=n;i++)
        dp[i][0] = 0;
    f(1);
    for(int i = m;i>=0;i--)
        if(dp[1][i]>=0){
            printf("%d",i);
            break;
        }
    return 0;
}

 

标签:结点,洛谷,选课,P2014,cnt,int,课程,修课,dp
From: https://www.cnblogs.com/cztq/p/16928186.html

相关文章

  • 洛谷P2015 二叉苹果树
    slojP10153.「一本通5.2例1」二叉苹果树P2015二叉苹果树题目描述有一棵苹果树,如果树枝有分叉,一定是分二叉(就是说没有只有一个儿子的结点)这棵树共有N个结点(叶子......
  • JSP课设:学生选课系统(附源码+调试)
    JSP学生选课管理系统学生选课管理系统功能概述(1)登录模块分为两种角色:学生角色、教师角色(2)教师模块:选课管理功能为对课程信息(课程编号、名称、学分)进行添加、修改、删除操......
  • 洛谷 P4018 Roy&October之取石子
    洛谷P4018Roy&October之取石子题意:\(n\)个石头,每次取\(p^k\)个石子(\(p\)是质数,\(k\in\N\)),取完最后一个的人获胜,问谁有必胜策略。只能说,MO题真的猛!结论:\(n\bmod......
  • 洛谷P1090 Java
    [NOIP2004提高组]合并果子/[USACO06NOV]FenceRepairG题目描述在一个果园里,多多已经将所有的果子打了下来,而且按果子的不同种类分成了不同的堆。多多决定把所有的......
  • 洛谷P2141 [NOIP2014 普及组] 珠心算测验
    [NOIP2014普及组]珠心算测验题目描述珠心算是一种通过在脑中模拟算盘变化来完成快速运算的一种计算技术。珠心算训练,既能够开发智力,又能够为日常生活带来很多便利,因而......
  • 洛谷P1614 爱与愁的心痛
    爱与愁的心痛题目背景(本道题目隐藏了两首歌名,找找看哪~~~)《爱与愁的故事第一弹·heartache》第一章。《我为歌狂》当中伍思凯神曲《舞月光》居然没赢给萨顶顶,爱与愁大......
  • 洛谷P1047 [NOIP2005 普及组] 校门外的树
    [NOIP2005普及组]校门外的树题目描述某校大门外长度为l的马路上有一排树,每两棵相邻的树之间的间隔都是1米。我们可以把马路看成一个数轴,马路的一端在数轴0的位置......
  • 洛谷P4956 [COCI2017-2018#6] Davor
    [COCI2017-2018#6]Davor题面翻译在征服南极之后,Davor开始了一项新的挑战。下一步是在西伯利亚、格林兰、挪威的北极圈远征。他将在2018年12月31日开始出发,在这之......
  • 洛谷P1085 [NOIP2004 普及组] 不高兴的津津
    [NOIP2004普及组]不高兴的津津题目描述津津上初中了。妈妈认为津津应该更加用功学习,所以津津除了上学之外,还要参加妈妈为她报名的各科复习班。另外每周妈妈还会送她去......
  • 洛谷 P3336 [ZJOI2013]话旧
    洛谷P3336[ZJOI2013]话旧图是洛谷搞的做点简单的观察发现,每一次下降必须经过零点。对于每个点,有两种状态,从上面走过来,记为下降;从下面走过来,记为上升。\((0,0)\)我们......