洛谷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. 两个stack实现一个queue

    package com.hzins.suanfa; import java.util.Stack; /** * 两个stack实现一个queue * @author Administrator * * ...

  2. log4j No appenders could be found for logger

    在main中加一句:BasicConfigurator.configure();

  3. linux命令学习笔记(37):date命令

    在linux环境中,不管是编程还是其他维护,时间是必不可少的,也经常会用到时间的运算,熟练运用date命令 来表示自己想要表示的时间,肯定可以给自己的工作带来诸多方便. .命令格式: date [参数 ...

  4. BZOJ5324 JXOI2018 守卫

    传送门 这是我见过的为数不多的良心九怜题之一 题目大意 给定一段$n$个点构成的折线,第$i$个折点的坐标是$(i,h_i)$,你可以在$i$点放置一个视野,定义$i$能看到$j$当且仅当$i$处有视 ...

  5. 调试 ASP 程序脚本

    调试 ASP 脚本 无论您的计划多么精密.经验多么丰富,脚本错误 (bug) 可能在最初就使您的 ASP 服务器端的脚本无法正确运行.也就是说调试,即查找和纠正脚本错误,对开发一个成功的和强健的 AS ...

  6. Boost库之asio io_service以及run、run_one、poll、poll_one区别

    一.io_service的作用 io_servie 实现了一个任务队列,这里的任务就是void(void)的函数.Io_servie最常用的两个接口是post和run,post向任务队列中投递任务,r ...

  7. 宽字符wchar_t和窄字符char区别和相互转换

    转自:http://blog.csdn.net/nodeathphoenix/article/details/7416725 1.    首先,说下窄字符char了,大家都很清楚,就是8bit表示的b ...

  8. event.keyCode 事件属性

    转自:http://www.runoob.com/jsref/event-key-keycode.html <!DOCTYPE html> <html> <head> ...

  9. java 设置Cookie值

    原文地址:http://blog.csdn.net/lansetiankong12/article/details/52622654 /** * 读取所有cookie * 注意二.从客户端读取Cook ...

  10. centos7 安装mysql 5.7多实例

    一. Mysql多实例即一台服务器上运行多个Mysql服务进程 ,开启不同的服务端口,通过不同的socket 监听不同的服务端口来提供各自的服务. 二. Mysql多例有以下几个特点: 1.  有效利 ...