【学习笔记】【题解】树形依赖 DP 选做
地址:https://www.cnblogs.com/FReQuenter5156/p/shuxingyilaidp.html/
简介
这类背包本质上是分组背包问题。
将一个节点的每一棵子树看作一组,进行分组背包。所谓分组背包,即在选择物品的时候,一开始将物品分为好几组,在选择时,可以从每一组中至多选择一件物品,问如何获得最大的价值,所以我们每次可以枚举这个组数,用 \(i\) 表示第几组,用 \(j\) 表示体积,用 \(k\) 来表示选择的物品,伪代码如下:
for (int i=0到组数)
for (int j=max_v到0)
for (int k=此组所有物品)
f[j]=max(f[j],f[j-v[k]]+w[k])
注意循环顺序。这个和 01 背包的道理类似。
例题
[CTSC1997] 选课
题面
在大学里每个学生,为了达到一定的学分,必须从很多课程里选择一些课程来学习,在课程里有些课程必须在某些课程之前学习,如高等数学总是在其它课程之前学习。现在有 \(N\) 门功课,每门课有个学分,每门课有一门或没有直接先修课(若课程 a 是课程 b 的先修课即只有学完了课程 a,才能学习课程 b)。一个学生要从这些课程里选择 \(M\) 门课程学习,问他能获得的最大学分是多少?
题解
定义
\(f_{i,j}\) 表示当前第 \(i\) 个点的子树内选 \(j\) 个点(不包括自己)的最大学分。
转移
直接套板子。初值在输入时已经设置好了,DP 中只要比大小。具体参考代码。
代码
#include<bits/stdc++.h>
#define MAXN 305
using namespace std;
int n,m,k[MAXN],s[MAXN],sz[MAXN],f[MAXN][MAXN];
vector<int> gv[MAXN];
void dfs(int now,int father){
sz[now]=1;
for(auto nx:gv[now]){
if(nx!=father) dfs(nx,now),sz[now]+=sz[nx];
}
}
void dp(int now,int father){
int sum=0;
for(auto nx:gv[now]){
if(nx==father) continue;
sum+=sz[nx];
dp(nx,now);
for(int j=sum;j>=0;j--){
for(int k=0;k<sz[nx];k++){
if(j-k>=1){
f[now][j]=max(f[now][j],f[now][j-k-1]+f[nx][k]);
}
}
}
}
}
signed main(){
cin>>n>>m;
for(int i=1;i<=n;i++){
cin>>k[i]>>s[i];
gv[k[i]].push_back(i);
f[i][0]=s[i];
}
dfs(0,0);
dp(0,0);
cout<<f[0][m];
}
有线电视网
题面
某收费有线电视网计划转播一场重要的足球比赛。他们的转播网和用户终端构成一棵树状结构,这棵树的根结点位于足球比赛的现场,树叶为各个用户终端,其他中转站为该树的内部节点。
从转播站到转播站以及从转播站到所有用户终端的信号传输费用都是已知的,一场转播的总费用等于传输信号的费用总和。
现在每个用户都准备了一笔费用想观看这场精彩的足球比赛,有线电视网有权决定给哪些用户提供信号而不给哪些用户提供信号。
写一个程序找出一个方案使得有线电视网在不亏本的情况下使观看转播的用户尽可能多。
题解
定义
\(f_{i,j}\) 表示到第 \(i\) 个点供应 \(j\) 个用户的最大收益。最后求答案的时候枚举下 \(f_{1,i}\geq 0\) 的最大 \(i\)。注意初值赋 -INF。
转移
也是套板子。直接看代码应该就能理解。
代码
#include<bits/stdc++.h>
#define fi first
#define se second
#define MAXN 3005
using namespace std;
vector<pair<int,int>> gv[MAXN];
int n,m,f[MAXN][MAXN],v[MAXN];
int dp(int now){
if(now>=n-m+1){
f[now][1]=v[now];
return 1;
}
int sum=0;
for(auto nx:gv[now]){
int tmp=dp(nx.fi);
sum+=tmp;
for(int j=sum;j>=1;j--){
for(int k=1;k<=tmp;k++){
if(j-k>=0) f[now][j]=max(f[now][j],f[now][j-k]+f[nx.fi][k]-nx.se);
}
}
}
return sum;
}
signed main(){
memset(f,-0x3f,sizeof(f));
cin>>n>>m;
for(int i=1;i<=n-m;i++){
int k;
cin>>k;
for(int j=1;j<=k;j++){
int a,c;
cin>>a>>c;
gv[i].push_back({a,c});
}
}
for(int i=n-m+1;i<=n;i++) cin>>v[i];
for(int i=1;i<=n;i++) f[i][0]=0;
int maxn=0;
dp(1);
for(int i=0;i<=m;i++) if(f[1][i]>=0) maxn=i;
cout<<maxn;
}
重建道路
题面
一场可怕的地震后,人们用 \(N\) 个牲口棚(编号 \(1\sim N\))重建了农夫 John 的牧场。由于人们没有时间建设多余的道路,所以现在从一个牲口棚到另一个牲口棚的道路是惟一的。因此,牧场运输系统可以被构建成一棵树。
John 想要知道另一次地震会造成多严重的破坏。有些道路一旦被毁坏,就会使一棵含有 \(P\) 个牲口棚的子树和剩余的牲口棚分离,John 想知道这些道路的最小数目。
题解
定义
\(f_{i,j}\) 表示当前第 \(i\) 个点为根的子树保留 \(j\) 个点(包括自己)删去的最小的边数。答案需要枚举所有的子树。
转移
其实也差不多。可以直接看代码。注意初始值 \(f_{i,1}\) 为每个点的出度。这题相对来说比较细节。如方程中的 -1,和自己的“父亲”的连边不能拆。
代码
#include<bits/stdc++.h>
using namespace std;
vector<int> gv[155];
int n,p,ans=0x3f3f3f3f,f[155][155],sz[155],od[155];
bool ir[155];
void dp(int now){
sz[now]=1;
if(!od[now]) return f[now][1]=0,void();
for(auto nx:gv[now]){
dp(nx);
sz[now]+=sz[nx];
for(int j=sz[now];j>=0;j--) for(int k=1;k<j;k++) f[now][j]=min(f[now][j],f[now][j-k]+f[nx][k]-1);
}
}
signed main(){
cin>>n>>p;
for(int i=1;i<n;i++){
int x,y;
cin>>x>>y;
gv[x].push_back(y),od[x]++,ir[y]=true;
}
memset(f,0x3f,sizeof(f));
for(int i=1;i<=n;i++) f[i][1]=od[i];
int root=0;
for(int i=1;i<=n;i++) if(!ir[i]) root=i;
dp(root);
for(int i=1;i<=n;i++){
if(i==root) ans=min(ans,f[i][p]);
else ans=min(ans,f[i][p]+1);
}
cout<<ans;
return 0;
}
拓展
[JSOI2016]最佳团体
题面
JSOI 信息学代表队一共有 \(N\) 名候选人,这些候选人从 \(1\) 到 \(N\) 编号。方便起见,JYY 的编号是 \(0\) 号。每个候选人都由一位编号比他小的候选人\(R_i\) 推荐。如果 \(R_i = 0\)?,则说明这个候选人是 JYY 自己看上的。
为了保证团队的和谐,JYY 需要保证,如果招募了候选人 \(i\),那么候选人 \(R_i\) 也一定需要在团队中。当然了,JYY 自己总是在团队里的。每一个候选人都有一个战斗值 \(P_i\) ,也有一个招募费用 \(S_i\) 。JYY 希望招募 \(K\) 个候选人(JYY 自己不算),组成一个性价比最高的团队。也就是,这 \(K\) 个被 JYY 选择的候选人的总战斗值与总招募费用的比值最大。
题解
简单说一下。比值类似于 最优比例生成树,可以使用分数规划,然后就可以去套板子了。
没来得及实现,可以参考洛谷题解。
【学习笔记】【题解】树形依赖 DP 选做的更多相关文章
- 【学习笔记】动态规划—各种 DP 优化
[学习笔记]动态规划-各种 DP 优化 [大前言] 个人认为贪心,\(dp\) 是最难的,每次遇到题完全不知道该怎么办,看了题解后又瞬间恍然大悟(TAT).这篇文章也是花了我差不多一个月时间才全部完成 ...
- .NET CORE学习笔记系列(2)——依赖注入[7]: .NET Core DI框架[服务注册]
原文https://www.cnblogs.com/artech/p/net-core-di-07.html 包含服务注册信息的IServiceCollection对象最终被用来创建作为DI容器的IS ...
- .NET CORE学习笔记系列(2)——依赖注入[6]: .NET Core DI框架[编程体验]
原文https://www.cnblogs.com/artech/p/net-core-di-06.html 毫不夸张地说,整个ASP.NET Core框架是建立在一个依赖注入框架之上的,它在应用启动 ...
- .NET CORE学习笔记系列(2)——依赖注入[4]: 创建一个简易版的DI框架[上篇]
原文https://www.cnblogs.com/artech/p/net-core-di-04.html 本系列文章旨在剖析.NET Core的依赖注入框架的实现原理,到目前为止我们通过三篇文章从 ...
- .NET CORE学习笔记系列(2)——依赖注入【3】依赖注入模式
原文:https://www.cnblogs.com/artech/p/net-core-di-03.html IoC主要体现了这样一种设计思想:通过将一组通用流程的控制权从应用转移到框架中以实现对流 ...
- .NET CORE学习笔记系列(2)——依赖注入【2】基于IoC的设计模式
原文:https://www.cnblogs.com/artech/p/net-core-di-02.html 正如我们在<控制反转>提到过的,很多人将IoC理解为一种“面向对象的设计模式 ...
- 「学习笔记」wqs二分/dp凸优化
[学习笔记]wqs二分/DP凸优化 从一个经典问题谈起: 有一个长度为 \(n\) 的序列 \(a\),要求找出恰好 \(k\) 个不相交的连续子序列,使得这 \(k\) 个序列的和最大 \(1 \l ...
- .NET CORE学习笔记系列(2)——依赖注入[5]: 创建一个简易版的DI框架[下篇]
为了让读者朋友们能够对.NET Core DI框架的实现原理具有一个深刻而认识,我们采用与之类似的设计构架了一个名为Cat的DI框架.在上篇中我们介绍了Cat的基本编程模式,接下来我们就来聊聊Cat的 ...
- .NET CORE学习笔记系列(2)——依赖注入【1】控制反转IOC
原文:https://www.cnblogs.com/artech/p/net-core-di-01.html 一.流程控制的反转 IoC的全名Inverse of Control,翻译成中文就是“控 ...
- 汇编入门学习笔记 (七)—— dp,div,dup
疯狂的暑假学习之 汇编入门学习笔记 (七)-- dp.div.dup 參考: <汇编语言> 王爽 第8章 1. bx.si.di.和 bp 8086CPU仅仅有4个寄存器能够用 &qu ...
随机推荐
- Svn安装客户端鼠标右键报错SendRpt.exe not found
kill 掉 重启资源管理器就好了
- 学习记录--C++作业3
1.类是一个模板吗? 是:类模板是一个抽象的类,代表类的一般特性,可以用类模板来创建类,所有的类都有共有的特性. 4.函数模板的实例化是什么? 模板函数,即函数 3.关于cin和cout说法正确的: ...
- Linux shell usage()使用说明
usage()类似于执行文件-help展示的内容,即告诉使用者有哪些参数选项可供使用. usage()格式 点击查看代码 #!/bin/bash usage() { echo "Usage: ...
- Axios的相关应用
Axios 的案例应用 要求利用axios实现之前利用AJAX实现的验证用户是否登录的案例 鉴于这两种语法的相似性,只需要在AJAX里面的注册界面里面的script标签里面包含的代码修改为如下代码即可 ...
- Bitcask — 日志结构的快速 KV 存储引擎
Bitcask 介绍 Bitcask 是一种高性能的键值存储引擎,基于日志结构和哈希索引来提供高速的读写操作和数据持久性,适用于处理大量写入请求和快速查找键值对的应用场景. 核心概念 Bitcask ...
- 【转载】谈谈GIS三维渲染引擎
> 原文地址:https://zhuanlan.zhihu.com/p/419667971 三维引擎 minemap: 是我们公司的产品,主要以earth的形态展示,支持矢量切片+倾斜数据(这一 ...
- Salesforce CPQ之后续慢慢看系列
salesforce核心两朵云,sales & service. 针对sales的quote / quote line item的报价功能,还是相对薄弱.针对sales,报价的准确性影响着成单 ...
- v-model 和 .sync
v-model的本质是父子组件间的通讯,父组件给子组件传递一个value自定义属性和input自定义事件:子组件接收value 并触发自定义事件修改value 父组件中 <Child v-mod ...
- better-scroll横向滚动、纵向滚动
<div ref="tab" class="tab"> <ul ref="tabWrapper" class=" ...
- abp(net core)+easyui+efcore实现仓储管理系统——ABP升级7.3上(五十八)
Abp(net core)+easyui+efcore实现仓储管理系统目录 abp(net core)+easyui+efcore实现仓储管理系统--ABP总体介绍(一) abp(net core)+ ...