博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Luogu P2014 选课 题解报告
阅读量:5220 次
发布时间:2019-06-14

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

【题目大意】

有n门选修课,每一门课都有固定的学分$S_i$,每个学生可以选m门课。有些选修课有先修课,每一门课最多只有一门先修课,求能获得的最多学分。

【思路解析】

设f[x][t]表示在以x结点为根的子树中选t门课能获得的最大学分,x的子结点集合为son[x],子结点个数为p,且对于x的第i个子结点son[i],以其为根结点的子树中选课数量为$C_i$,则转移方程为:$$f[x][t]=max(\sum_{i=1}^{p}f[son[i]][c[i]])+s[i](满足\sum_{i=1}^{p}c[i]=t-1)$$这个方程其实是一个分组背包模型,有p组物品,每组物品有t-1个,其中第i组的第j个物品体积为j,价值为f[son[i]][j],背包的容积为t-1。

【代码实现】

1 #include
2 #define rg register 3 #define go(i,a,b) for(rg int i=a;i<=b;i++) 4 #define back(i,a,b) for(rg int i=a;i>=b;i--) 5 #define ll long long 6 #define mem(a,b) memset(a,b,sizeof(a)) 7 using namespace std; 8 const int N=302; 9 vector
son[N];10 int f[N][N],n,m,s[N];11 void dp(int x){12 f[x][0]=0;13 int size=son[x].size();14 go(i,0,size-1){
//循环子结点(物品)15 int y=son[x][i];16 dp(y);17 back(t,m,0) back(j,t,0)18 //倒叙循环当前选课总门数(当前背包体积)19 //循环更深子树上的选课门数(组内物品),此处使用倒序是为了正确处理组内体积为0的物品20 if(t-j>=0) f[x][t]=max(f[x][t],f[x][t-j]+f[y][j]);21 }22 if(x!=0)//x不为0时,选修x本身要占掉一门课,并获得相应学分23 back(t,m,1) f[x][t]=f[x][t-1]+s[x];24 return;25 }26 int main(){27 scanf("%d%d",&n,&m);28 go(i,1,n){29 int fa;30 scanf("%d%d",&fa,&s[i]);31 son[fa].push_back(i);32 }33 mem(f,0);34 dp(0);35 printf("%d\n",f[0][m]);36 return 0;37 }
代码戳这里

 

转载于:https://www.cnblogs.com/THWZF/p/11002226.html

你可能感兴趣的文章
洛谷P2777
查看>>
Ajax
查看>>
PHPStorm2017设置字体与设置浏览器访问
查看>>
android开发学习笔记:圆角的Button
查看>>
Activity简介
查看>>
jqGrid树
查看>>
循环-12. 打印九九口诀表(15)
查看>>
oracle树状索引详解(图摘取《收获不止oracle》)
查看>>
Android Studio 设置代码提示和代码自动补全快捷键--Eclipse 风格 - 转
查看>>
ORACLE基本操作备忘
查看>>
Maven学习:项目之间的关系
查看>>
SQL查询总结 - wanglei
查看>>
安装cocoa pods时出现Operation not permitted - /usr/bin/xcodeproj的问题
查看>>
makefile中使用变量
查看>>
GIT笔记:将项目发布到码云
查看>>
JavaScript:学习笔记(7)——VAR、LET、CONST三种变量声明的区别
查看>>
JavaScript 鸭子模型
查看>>
PHP典型功能与Laravel5框架开发学习笔记
查看>>
SQL Server 如何查询表定义的列和索引信息
查看>>
项目上传到github上
查看>>