洛谷P2014 选课

题目描述

在大学里每个学生,为了达到一定的学分,必须从很多课程里选择一些课程来学习,在课程里有些课程必须在某些课程之前学习,如高等数学总是在其它课程之前学习。现在有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门课程的最大得分。

好困啊~~~

这道题做的不好。

一开始的做法:

​ 设\(f(i)(j)\)表示在以i为根的子树中,选择j个点并且一定选择i的最大价值。

​ 状态倒是设对了。但是转移就不会了。

​ 想的是树上的分组背包。

​ 将当前点的每个儿子看成一类物品,然后就可以枚举这一类物品中选多少个。

​ 应该是没问题,但是太困写不动了。。。

​ 而且我犯了一个错误就是对于当前的点u,应该枚举一层这个点的子树中选择多少个,所以我们应该记录当前的这个数的大小,并用其作为上界,但我是写了一个记忆化搜索每一次将传入的参数t当做上界,就不对了。

好了,感觉我的做法思路很乱套。

开始说一说正确做法吧。

​ 状态很好设:设\(f(i)(j)\)表示在以i为根的子树中,选择j个点并且一定选择i的最大价值。

​ 重点是怎么去推。

​ 这里用到了一个东西叫做多叉转二叉。也就是说我们要记录当前节点的子树大小作为枚举上界,所以我们可以每一次将当前点现在所枚举到的子树的大小加上,就是开一个变量记录当前的子树大小,在转移之前先将当前枚举到的子节点的size加上。

​ 这里有一个DP的思想,个人感觉类似记忆化搜索吧,挺重要的,就是我们当前要用v去转移u的状态,那么肯定的,我们应该知道v的状态(当然也可以在转移时记忆化搜索出v的状态),所以我们在转移u之前就应该先将v转移好。

#include<iostream>
#include<cstdio>
using namespace std;
const int wx=3017;
inline int read(){
int sum=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){sum=(sum<<1)+(sum<<3)+ch-'0';ch=getchar();}
return sum*f;
}
struct e{
int nxt,to;
}edge[wx*2];
int n,m,num,x;
int head[wx],a[wx],f[317][317],size[wx];
void add(int from,int to){
edge[++num].nxt=head[from];
edge[num].to=to;
head[from]=num;
}
int dfs(int u){
f[u][1]=a[u];int tot=1;
for(int i=head[u];i;i=edge[i].nxt){
int v=edge[i].to;tot+=dfs(v);
for(int j=tot;j>=1;j--){
for(int k=1;k<j;k++){
f[u][j]=max(f[u][j],f[u][j-k]+f[v][k]);
}
}
}
return tot;
}
int main(){
n=read();m=read();
for(int i=1;i<=n;i++){
x=read();a[i]=read();
add(x,i);
}
dfs(0);
printf("%d\n",f[0][m+1]);
return 0;
}
//f[i][j]表示在以i为根的子树中选择j个点并且一定选i这个点的最大价值
//f[i][j]=max(f[i][j],f[v][k]+a[v]+f[i][j-k])

树形DP 洛谷P2014 选课的更多相关文章

  1. 洛谷 P2014 选课(树形背包)

    洛谷 P2014 选课(树形背包) 思路 题面:洛谷 P2014 如题这种有依赖性的任务可以用一棵树表示,因为一个儿子要访问到就必须先访问到父亲.然后,本来本题所有树是森林(没有共同祖先),但是题中的 ...

  2. 洛谷P2014 选课 (树形dp)

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

  3. 洛谷P2014 选课

    首先分析题目,这是一道树形dp的题目,是树形背包类的问题,以为每门课的先修课只有一门,所以这一定可以 构成一个森林结构,于是我们可以设计一个虚拟的根节点作为森林的根. 状态转移方程如下 dp[v][k ...

  4. 洛谷 P2014 选课

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

  5. 洛谷 P2014 选课 && caioj 1108 树形动态规划(TreeDP)3:选课

    这里的先后关系可以看成节点和父亲的关系 在树里面,没有父亲肯定就没有节点 所以我们可以先修的看作父亲,后修的看作节点 所以这是一颗树 这题和上一道题比较相似 都是求树上最大点权和问题 但这道题是多叉树 ...

  6. 洛谷P2014——选课

    题目:https://www.luogu.org/problemnew/show/P2014 树状DP,注意枚举当前子树中选几个时的边界. 代码如下: #include<iostream> ...

  7. 洛谷—— P2014 选课

    https://www.luogu.org/problem/show?pid=2014 题目描述 在大学里每个学生,为了达到一定的学分,必须从很多课程里选择一些课程来学习,在课程里有些课程必须在某些课 ...

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

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

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

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

随机推荐

  1. lombok_学习_00_资源帖

    二.参考资料 Java界的神器-使用Lombok来消除你的冗余代码量 Lombok:让JAVA代码更优雅 Lombok开发指南

  2. 3_observer

    #Observer 成就系统 achievements system 玩家完成某种成就后,通知监督者,监督者做出相应出来 ``` //简单来说就是事件触发的时候, 通知监督者 class Observ ...

  3. 什么是DMIPS

    MIPS: Million Instructions executed Per Second,每秒百万条指令,用来计算同一秒内系统的处理能力 DMIPS: Dhrystone Million Inst ...

  4. 20179203 《Linux内核原理与分析》第十周作业

    第17章 设备与模块 一.设备类型 1. Linux及Unix系统: 块设备 字符设备 网络设备 2.块设备: 通常缩写为blkdev,它是可寻址的,寻址以块为单位,块大小随设备不同而不同:块设备通常 ...

  5. bzoj 4260: REBXOR Trie+乱搞

    题目大意: http://www.lydsy.com/JudgeOnline/problem.php?id=4260 题解: 啊啊啊. 被这种SB题坑了半天. 求出异或前缀和后 从n到1枚举\(r_1 ...

  6. 洛谷【P1480】A/B Problem

    题目传送门:https://www.luogu.org/problemnew/show/P1480 高精除低精板子题,灵性地回忆一下小学时期列竖式的草稿纸即可. 时间复杂度:\(O(len)\) 空间 ...

  7. 洛谷 P4547 & bzoj 5006 随机二分图 —— 状压DP+期望

    题目:https://www.luogu.org/problemnew/show/P4547 https://www.lydsy.com/JudgeOnline/problem.php?id=5006 ...

  8. 数据结构-二叉搜索树的js实现

    一.树的相关概念 1.基本概念 子树 一个子树由一个节点和它的后代构成. 节点的度 节点所拥有的子树的个数. 树的度 树中各节点度的最大值 节点的深度 节点的深度等于祖先节点的数量 树的高度 树的高度 ...

  9. python mysql 查询返回字典结构

    cur = self.conn.cursor(MySQLdb.cursors.DictCursor)加上MySQLdb.cursors.DictCursor可以返回字典结构 {列名:值} class ...

  10. HDOJ1166(线段树点修改)

    敌兵布阵 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submis ...