cogs 1199选课(树形dp 背包或多叉转二叉
http://cogs.pro:8080/cogs/problem/problem.php?pid=vQyiJkkPP
题意:给m门课,每门课在上完其先修课后才能上,要你从中选n门课使得总学分尽可能大。
思路:背包,没有先修课看成其先修课编号为0,求一个f[0][n]的背包,表示以0为根的树选n个结点的最大总权值,设x为根,y为x的孩子,对每个孩子,dfs(y),然后f[[x][t]=max(f[x][t],f[x][t-j]+f[y][j])用每个孩子更新x,最后若x不是0,再用自己的权值更新自己。但背包好像不能记录路径。
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;++i)
#define dep(i,a,b) for(int i=a;i>=b;--i)
using namespace std;
const int MAXN=;
int read(){
int sum=,flag=;
char c;
for(;c<''||c>'';c=getchar())if(c=='-') flag=-;
for(;c>=''&&c<='';c=getchar())sum=(sum<<)+(sum<<)+c-'';
return sum*flag;
}
int n,m;
int v[MAXN];
vector<int>son[MAXN];
int f[MAXN][MAXN];
void init(){
n=read();m=read();
rep(i,,n){
int y;
y=read();v[i]=read();
son[y].push_back(i);
}
}
void DP(int x){
f[x][]=;
for(int i=;i<son[x].size();++i){
int y=son[x][i];
DP(y);
dep(t,m,)
dep(j,t,)
if(t>=j)
f[x][t]=max(f[x][t],f[x][t-j]+f[y][j]);
}
if(x!=) dep(t,m,) f[x][t]=f[x][t-]+v[x];
}
int main(){
init();
DP();
printf("%d",f[][m]);
return ;
}
多叉转二叉,左孩子右兄弟。
若选根结点,f[i][j] = f[br[i][j]
若不选根结点,f[i][j] = f[ch[i]][k]+f[br[i]][j-1-k]+v[i]
递归寻找路径方法类似。
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;++i)
#define dep(i,a,b) for(int i=a;i>=b;--i)
using namespace std;
const int MAXN=;
int read(){
int sum=,flag=;
char c;
for(;c<''||c>'';c=getchar())if(c=='-') flag=-;
for(;c>=''&&c<='';c=getchar())sum=(sum<<)+(sum<<)+c-'';
return sum*flag;
}
int n,m;
int v[MAXN];
int br[MAXN],ch[MAXN];
bool ans[MAXN];
int f[MAXN][MAXN];
void init(){
n=read();m=read();
int x;
rep(i,,n){
x=read();
v[i]=read();
if(!x) x=n+;
br[i]=ch[x];
ch[x]=i;
}
memset(f,-,sizeof f);
}
void DP(int x,int y){
if(f[x][y]>=) return;
if(!x||!y) {f[x][y]=;return;}
DP(br[x],y);
rep(i,,y-){
DP(br[x],i);
DP(ch[x],y-i-);
f[x][y]=max(f[x][y],max(f[br[x]][y],f[br[x]][i]+f[ch[x]][y-i-]+v[x]));
}
}
void path(int x,int y){
if(!x||!y) return;
if(f[x][y]==f[br[x]][y]) path(br[x],y);
else {
rep(i,,y-){
if(f[x][y]==f[br[x]][i]+f[ch[x]][y-i-]+v[x]){
path(br[x],i);
path(ch[x],y-i-);
ans[x]=;
return;
}
}
}
}
int main(){
init();
DP(ch[n+],m);
printf("%d\n",f[ch[n+]][m]);
path(ch[n+],m);
rep(i,,n) if(ans[i]) printf("%d\n",i);
return ;
}
cogs 1199选课(树形dp 背包或多叉转二叉的更多相关文章
- Codevs1378选课[树形DP|两种做法(多叉转二叉|树形DP+分组背包)---(▼皿▼#)----^___^]
题目描述 Description 学校实行学分制.每门的必修课都有固定的学分,同时还必须获得相应的选修课程学分.学校开设了N(N<300)门的选修课程,每个学生可选课程的数量M是给定的.学生选修 ...
- URAL_1018 Binary Apple Tree 树形DP+背包
这个题目给定一棵树,以及树的每个树枝的苹果数量,要求在保留K个树枝的情况下最多能保留多少个苹果 一看就觉得是个树形DP,然后想出 dp[i][j]来表示第i个节点保留j个树枝的最大苹果数,但是在树形过 ...
- TYVJ P1051 选课 Label:多叉转二叉&&树形dp(虐心♥)
描述 学校实行学分制.每门的必修课都有固定的学分,同时还必须获得相应的选修课程学分.学校开设了N(N<300)门的选修课程,每个学生可选课程的数量M是给定的.学生选修了这M门课并考核通过就能获得 ...
- joyOI 选课 【树形dp + 背包dp】
题目链接 选课 题解 基础背包树形dp #include<iostream> #include<cstdio> #include<cmath> #include&l ...
- 『选课 树形dp 输出方案』
这道题的树上分组背包的做法已经在『选课 有树形依赖的背包问题』中讲过了,本篇博客中主要讲解将多叉树转二叉树的做法,以便输出方案. 选课 Description 学校实行学分制.每门的必修课都有固定的学 ...
- hdu1561 The more, The Better (树形dp+背包)
题目链接:http://acm.split.hdu.edu.cn/showproblem.php?pid=1561 思路:树形dp+01背包 //看注释可以懂 用vector建树更简单. 代码: #i ...
- codeforces 212E IT Restaurants(树形dp+背包思想)
题目链接:http://codeforces.com/problemset/problem/212/E 题目大意:给你一个无向树,现在用两种颜色去给这颗树上的节点染色.用(a,b)表示两种颜色分别染的 ...
- 选课 树形DP+多叉树转二叉树+dfs求解答案
问题 A: 选课 时间限制: 1 Sec 内存限制: 128 MB 题目描述 大 学里实行学分.每门课程都有一定的学分,学生只要选修了这门课并考核通过就能获得相应的学分.学生最后的学分是他选修的各门 ...
- BZOJ.1017.[JSOI2008]魔兽地图(树形DP 背包DP)
题目链接 树形DP,考虑子节点对父节点的贡献. 设f[x][i][j]表示当前为x,用i个x去合成上一层装备,花费为j的最大价值. 由子节点转移时 是一个分组背包,需要一个辅助数组g[i][j]表示前 ...
随机推荐
- 从后端到前端之Vue(五)小试路由
一开始我还以为vue的路由只能用在工程化的项目里面呢,然后研究了一下才发现,在脚本化里面也是可以用的.其实呢不管在哪里用,把原理研究明白就对了. 一. 官网demo 这里不得不吐槽一下官网,写的不清不 ...
- python交互界面无法使用方向键
问题 python交互界面无法使用方向键,按方向键全变成^[[^C这类型的字符 解决办法 办法1: 使用yum安装readline.readline-devel,然后重装python 这种方法太麻烦了 ...
- CentOS7使用yum安装ceph rpm包
1. 安装centos7对扩展repo的支持yum install yum-plugin-priorities保证下面的选项是开启的[main]enabled = 1 2. 安装 release.ke ...
- 7.源码分析---SOFARPC是如何实现故障剔除的?
我在服务端引用那篇文章里面分析到,服务端在引用的时候会去获取服务端可用的服务,并进行心跳,维护一个可用的集合. 所以我们从客户端初始化这部分说起. 服务连接的维护 客户端初始化的时候会调用cluste ...
- Spark 系列(三)—— 弹性式数据集RDDs
一.RDD简介 RDD 全称为 Resilient Distributed Datasets,是 Spark 最基本的数据抽象,它是只读的.分区记录的集合,支持并行操作,可以由外部数据集或其他 RDD ...
- JVM系列(2)- jmap+mat实战内存溢出
熟悉几个监控JVM的常用命令 1. jps -l 查出当前服务器运行的java进程 --- 2. jinfo用法(结合jps -l查到进程ID) 1).查看最大堆内存:jinfo -flag MaxH ...
- 修改 jupyter notebook的默认文件夹位置
安装好Anaconda 3以后,就可以使用Jupyter notebook了,但是我们打开Jupyter notebook后,发现界面是一个默认的目录,这个目录在哪里?如果想把自己写的程序文件保存在自 ...
- NS3中一些难以理解的常数
摘要:在NS3的学习中,PHY MAC中总有一些常数,需要理解才能修改.如帧间间隔等.那么,本文做个简单分析,帮助大家理解.针对802.11标准中MAC协议. void WifiMac::Conf ...
- node 删除和复制文件或文件夹
[toc] 创建时间:2019-08-12 注意:在win10,v10.16.1 环境运行无问题 首先引入相关包(会在使用处具体说明): const fs = require('fs') const ...
- Linux常用命令之ftp
FTP是Internet用户使用最频繁的文件上传.下载的命令之一.linux ftp用命令的方式来控制在本机和远程ftp服务器之间传送文件.ftp中的命令包括上传文件(单个.多个),下载文件(单个.多 ...