博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
「Luogu2014」 选课
阅读量:6311 次
发布时间:2019-06-22

本文共 1132 字,大约阅读时间需要 3 分钟。

树上背包问题的典例,记下来


solution

\(dp[x][t]\)表示以\(x\)为子树,选\(t\)门课获得的最大学分

\(p\)\(x\)的子节点数量,\(c_i\)\(x\)的子节点\(y_i\)选修的课数

转移方程如下

\[dp[x][t]=max_{\sum_{i=1}^pc_i=t-1}\{\sum_{i=1}^pdp[y_i][c_i]\}+pnt[x]\]

事实上,这是一个分组背包模型,对于每个节点\(x\),每个子节点\(y_i\)是一个组,在其中选取不超过\(1\)个元素\(c_i\)加入背包。将当前枚举到的组作为阶段

对于没有先修课的课程,我们可以将一个超级根节点\(0\)作为它们的父节点,方便计算

Code

#include 
#include
#include
#include
#include
#include
#include
#define maxn 305#define maxm 305using namespace std;typedef long long ll;int n,m;vector
son[maxn];int prt[maxn];int pnt[maxn];int dp[maxn][maxm];void DP(int u){ for(register int i=0;i
=0;--t)//枚举背包已经放入的体积 for(register int j=t;j>=0;--j) dp[u][t]=max(dp[u][t],dp[u][t-j]+dp[v][j]); } if(u!=0)//除超级根节点外,每个节点的选取都会获得pnt[u]的学分 for(register int t=m;t>0;--t) dp[u][t]=dp[u][t-1]+pnt[u];}int main(){ scanf("%d%d",&n,&m); int k; for(register int i=1;i<=n;++i) { scanf("%d%d",&k,&pnt[i]); prt[i]=k; } for(register int i=1;i<=n;++i) son[prt[i]].push_back(i); DP(0); printf("%d",dp[0][m]); return 0;}

转载于:https://www.cnblogs.com/lizbaka/p/10246427.html

你可能感兴趣的文章
jquery mobile script
查看>>
SDL源码阅读笔记(1) 基本模块
查看>>
MyBatis 物理分页
查看>>
HDU4550+贪心
查看>>
记录下Lambda常用的表现形式
查看>>
iOS \U7ea2 乱码 转换
查看>>
python开发_imghdr_图像格式支持
查看>>
消息传递通道
查看>>
Android 常用dialog提示对话框
查看>>
Android调用WebService(转)
查看>>
leetcode -- Reverse Integer
查看>>
在SSIS包中的事务处理
查看>>
android之ViewStub的使用
查看>>
如何将win7安装到 移动硬盘/U盘 及 VHD、BCD等相关知识 链接汇总
查看>>
工作经验总结:百万数据引发的性能瓶颈问题
查看>>
Fedora下载地址
查看>>
UIView总结
查看>>
第二、UIScrollView的使用大全
查看>>
WPF, WPF Browser Application(XBAP) 和 Silverlight 的区别
查看>>
Android给拼接好的Bitmap加上个性化边框
查看>>