题目描述 Description

学校实行学分制。每门的必修课都有固定的学分,同时还必须获得相应的选修课程学分。学校开设了N(N<300)门的选修课程,每个学生可选课程的数量M是给定的。学生选修了这M门课并考核通过就能获得相应的学分。

  在选修课程中,有些课程可以直接选修,有些课程需要一定的基础知识,必须在选了其它的一些课程的基础上才能选修。例如《Frontpage》必须在选修了《Windows操作基础》之后才能选修。我们称《Windows操作基础》是《Frontpage》的先修课。每门课的直接先修课最多只有一门。两门课也可能存在相同的先修课。每门课都有一个课号,依次为1,2,3,…。 例如:

【详见图片】
表中1是2的先修课,2是3、4的先修课。如果要选3,那么1和2都一定已被选修过。   你的任务是为自己确定一个选课方案,使得你能得到的学分最多,并且必须满足先修课优先的原则。假定课程之间不存在时间上的冲突。

输入描述 Input Description

输入文件的第一行包括两个整数N、M(中间用一个空格隔开)其中1≤N≤300,1≤M≤N。 
以下N行每行代表一门课。课号依次为1,2,…,N。每行有两个数(用一个空格隔开),第一个数为这门课先修课的课号(若不存在先修课则该项为0),第二个数为这门课的学分。学分是不超过10的正整数。

输出描述 Output Description

输出文件只有一个数,实际所选课程的学分总数。

样例输入 Sample Input

7 4
2 2
0 1
0 4
2 1
7 1
7 6
2 2

样例输出 Sample Output

13

数据范围及提示 Data Size & Hint

各个测试点1s

思路(Easy sir博客上的):

  继续照着三步的方法判断:一,题目大致一看,有点像有依赖的背包问题,于是你扭头就走,关掉了我的《树规》,打开了崔神犇的《背包九讲》。然后你哭了,因为有依赖的背包问题只限定于一个物品只依赖于一个物品,而没有间接的依赖关系。有依赖的背包问题的模型,根本解决不了。崔神告诉你,这属于树规的问题,不属于他背包的范围了。好了,回过来,我们接着分析。发现这是一棵树,还是一棵多叉树,嗯,很好,确定是树规了。

  然后第二步,建树,一看数据范围邻接矩阵;

  第三步动规方程:f[i][j]表示以i为节点的根的选j门课的最大值,然后有两种情况: i不修,则i的孩子一定不修,所以为0;i修,则i的孩子们可修可不修(在这里其实可以将其转化为将j-1个对i的孩子们进行资源分配的问题,也属于背包问题);答案是f[1][m]。问题圆满解决,一气呵成。

  但……

  身为追求完美的苦*程序猿的我们,不可以将它更简单一点呢?

  多叉转二叉。

  因为之前我们说过“在树的存储结构上,我们一般选的都是二叉树,因为二叉树可以用静态数组来存储,并且状态转移也很好写(根节点只和左子节点和右子节点有关系)。”所以转换成二叉树无疑是一种不错的选择。

  我们开两个一维数组,b[i](brother)&c[i](child)分别表示节点i的孩子和兄弟,以左孩子和右兄弟的二叉树的形式存储这样,根节点之和两个节点有关系了,状态转移的关系少了,代码自然也就好写了。

  我们依旧f[i][j]表示以i为节点的根的选j门课的最大值,那么两种情况:1.根节点不选修则f[i][j]=f[b[i]][j];2.根节点选修f[i][j]=f[c[i]][k]+f[b[i]][j-k-1]+a[i](k表示左孩子学了k种课程);取二者的最大值即可。

代码:

#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm> using namespace std;
const int maxn = ;
int dp[maxn][maxn],value[maxn],brother[maxn],child[maxn],tmpa,tmpb,n,m; void dfs(int item,int room){
if(dp[item][room] >=) return;
if(item == || room == ){
dp[item][room] = ;
return;
}
dfs(brother[item],room);
for(int k = ;k < room;k++){
dfs(brother[item],k);
dfs(child[item],room-k-);
dp[item][room] = max(dp[item][room],max(dp[brother[item]][room],dp[brother[item]][k] + dp[child[item]][room-k-] + value[item]));
}
return;
} int main(){
memset(dp,-,sizeof(dp));
cin>>n>>m;
for(int i = ;i <= n;i++){
cin>>tmpa>>tmpb;
value[i] = tmpb;
if(tmpa == ) tmpa = n + ;
brother[i] = child[tmpa];
child[tmpa] = i;
}
dfs(child[n+],m);
cout<<dp[child[n+]][m];
return ;
}

codevs 1378 选课的更多相关文章

  1. 树形DP+(分组背包||二叉树,一般树,森林之间的转换)codevs 1378 选课

    codevs 1378 选课 时间限制: 1 s  空间限制: 128000 KB  题目等级 : 钻石 Diamond  题目描述 Description 学校实行学分制.每门的必修课都有固定的学分 ...

  2. codevs 1378选课 树形DP

    #include<cstdio> #include<cstring> #include<algorithm> using namespace std; ],tr[] ...

  3. codevs 1378 选课 (树形DP)

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

  4. [CTSC2001]1378 选课

      1378 选课 题目描述 学校实行学分制.每门的必修课都有固定的学分,同时还必须获得相应的选修课程学分.学校开设了N(N<300)门的选修课程,每个学生可选课程的数量M是给定的.学生选修了这 ...

  5. 选课(codevs 1378)

    题目描述 Description 学校实行学分制.每门的必修课都有固定的学分,同时还必须获得相应的选修课程学分.学校开设了N(N<300)门的选修课程,每个学生可选课程的数量M是给定的.学生选修 ...

  6. 树形dp练习

    /*poj 1463 最小点覆盖 匈牙利*/ #include<iostream> #include<cstdio> #include<cstring> #defi ...

  7. codevs 3289 花匠

    题目:codevs 3289 花匠 链接:http://codevs.cn/problem/3289/ 这道题有点像最长上升序列,但这里不是上升,是最长"波浪"子序列.用动态规划可 ...

  8. codevs 1082 线段树练习 3(区间维护)

    codevs 1082 线段树练习 3  时间限制: 3 s  空间限制: 128000 KB  题目等级 : 大师 Master 题目描述 Description 给你N个数,有两种操作: 1:给区 ...

  9. codevs 1285 二叉查找树STL基本用法

    C++STL库的set就是一个二叉查找树,并且支持结构体. 在写结构体式的二叉查找树时,需要在结构体里面定义操作符 < ,因为需要比较. set经常会用到迭代器,这里说明一下迭代器:可以类似的把 ...

随机推荐

  1. 一命令安装nginx

    #!/bin/bash yum -y install wget pcre-devel openssl openssl-devel libtool gcc automake autoconf libto ...

  2. php中除法取整的方法(round,ceil,floor)

    PHP中遇到需要将除法所得结果取整的情况时,就需要用到以下方法: 1. round:四舍五入 round() 函数对浮点数进行四舍五入. 语法:round(x, prec) 参数 描述 x 可选.规定 ...

  3. window.form增删改查

    效果展示: 查询: 可以查询姓名:民族:姓名+民族:都是空的查询全部 取值取得是姓名: 删除: 修改: 先选中查询之后修改: 添加: 代码部分: 第一张表: 第二张表:主表,民族代码加名称 natio ...

  4. AJPFX关于Java NIO的概述总结

    Java NIO 由以下几个核心部分组成: Channels Buffers Selectors 虽然Java NIO 中除此之外还有很多类和组件,但在我看来,Channel,Buffer 和 Sel ...

  5. 依赖注入(IOC) 详解

    https://blog.csdn.net/qq_27093465/article/details/52547290 https://blog.csdn.net/qq_27093465/article ...

  6. shell编写的多服务器自动互信脚本(安装ceph)

    相信大家都使用过分布式存储,而在分布式存储中较为出色的非ceph莫属了,但是这里就不深入聊ceph啦,我们只是聊聊安装ceph时遇到的问题. ceph需要多台主机进行ssh互信.三台还能忍受,但是当超 ...

  7. mysql-oracle

    1.oracle数据崩导入时部分字段数据太长导入失败:原因是两边oracle字符集不一致 https://www.cnblogs.com/baoposhou/p/5669778.html 2.orac ...

  8. Objective-C 是动态语言

    Objective-C 的动态性是由 runtime 相关的库赋予的. 当然其他语言也完全可以运行在一个 Runtime 库上而获得动态性,由于多数高级语言的诞生都对应着一种编译器,因此将编译器的特性 ...

  9. mysql 添加记录或者删除记录

    insert into tableName (prod1,pord2,... ) values (v1,v2,...) [,(v1,v2,...),(v1,v2,...)] 程度从强到弱 1.drop ...

  10. 常用的HTTP方法有哪些?

    GET: 用于请求访问已经被URI(统一资源标识符)识别的资源,可以通过URL传参给服务器POST:用于传输数据给服务器,主要功能与GET方法类似,但一般推荐使用POST方式.PUT: 传输数据,报文 ...