Luogu P2014 选课 题解报告

题目传送门

【题目大意】

有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<bits/stdc++.h>
 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<int> 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

时间: 2024-08-19 00:11:01

Luogu P2014 选课 题解报告的相关文章

MZOJ 1132 &amp;&amp; LuoGu P2014 选课

MZOJ 1132 && LuoGu P2014 选课    [传送门] #include<bits/stdc++.h> #define maxn 100000 #define maxm 500 using namespace std; int k=0,head[maxn]; int f[maxm][maxm],w[maxn]; int ans=0; int N,M; struct node{ int v,nxt; }e[maxn<<1]; void adde(in

P2014 选课 题解(树形DP)

题目链接 P2014 选课 解题思路 树形动归,用\(f[i][j]\)表示以\(i\)为根,\(j\)个子节点(不包括自己)的最大学分 首先根据题意建图,用根节点\(0\)将森林连成树. 从根节点开始\(DFS\)遍历,遍历到叶节点后回溯,回溯过程中将\(f[i][j]\)更新,利用背包的思想. \(DFS\)过程中,\(num\)为离根节点0更近的定点,遍历的\(i\)为\(num\)的子节点,容易得出递推关系式: \(f[num][j]=max\{f[num][j],f[num][j-k-

【题解】Luogu P2014 选课

Problem 树上背包问题的典例,记下来 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\)是一个组,在其中选

Luogu P2014 选课 (树形DP)

题目 题目描述 在大学里每个学生,为了达到一定的学分,必须从很多课程里选择一些课程来学习,在课程里有些课程必须在某些课程之前学习,如高等数学总是在其它课程之前学习.现在有N门功课,每门课有个学分,每门课有一门或没有直接先修课(若课程a是课程b的先修课即只有学完了课程a,才能学习课程b).一个学生要从这些课程里选择M门课程学习,问他能获得的最大学分是多少? 输入输出格式 输入格式: 第一行有两个整数N,M用空格隔开.(1<=N<=300,1<=M<=300) 接下来的N行,第i+1行

Luogu P2014 选课

题面 对于这道题,我们考虑在树形dp上套背包.我们会非常自然的采用dfs扫描整棵树,然后对树上的每个节点都进行一次背包. 计\(dp[i][j]\)为在以第\(i\)号节点为根结点的子树中,用题目中选法选取\(j\)项的最大值. 我们在dfs的过程中,采用递归的方式,在子节点都处理完之后,便考虑将所有子节点的答案综合,得到当前节点的答案. 很显然,就是在容量为\(j\)的01背包中放下\(i\)节点的所有子节点背包中的答案,我们很容易想到下面的DP方程 \[f[x][j]=max(f[to][k

LuoGu P2014选课(人生第一个树上背包)

(著名哲学家沃兹基硕德曾经说过:“$QuickSilverX$ $is$ $a$ $BB$”) 就是课与课可能有一些优先关系 这种关系我们可以通过图论建模来解决 不难发现,若将优先选修课向当前课连边,就会生成森林(每门课只有一个选修课,也就只有一条入边) 将所有无入边(没有优先课)的结点与0相连,形成树 ~~不难~~发现这是一个树上DP与背包... 树本身就是个递归的结构,我们每个结点的状态肯定是先递归处理儿子结点的状况来转移的 定义状态 $F[i][j][k]$ 表示第 $i$ 的前 $j$

结题报告:luogu P2014

题目链接:P2014 选课 简单的树形\(dp\),借助\(dfs\)实现. 一般的树形\(dp\)数组是需要二维的,其中一维记录节点(编号或父/子节点的状态(有时三维)),另一维记录权值或计数. 重要的是判断从根节点\(dp\)还是从叶节点\(dp\),显然此题需从叶节点开始. 我们记\(dp[i][j]\)为从\(i\)节点向下选\(j\)个节点最大权值(注意不包括自己),易得方程: \[dp[i][j]=max(dp[i][j],dp[i][j-k-1]+dp[i_{son}][k]\]

cojs 强连通图计数1-2 题解报告

OwO 题目含义都是一样的,只是数据范围扩大了 对于n<=7的问题,我们直接暴力搜索就可以了 对于n<=1000的问题,我们不难联想到<主旋律>这一道题 没错,只需要把方程改一改就可以了 首先我们考虑不合法的方案强连通分量缩点后一定是DAG 考虑子问题:DAG计数 做法可以参考<cojs DAG计数1-4 题解报告> 这里给出转移方程 f(n)=sigma((-1)^(k-1)*C(n,k)*2^(k*(n-k))*f(n-k)) 如果考虑上强连通分量缩点的情况呢? 我

树形DP 洛谷P2014 选课

P2014 选课 题目描述 在大学里每个学生,为了达到一定的学分,必须从很多课程里选择一些课程来学习,在课程里有些课程必须在某些课程之前学习,如高等数学总是在其它课程之前学习.现在有N门功课,每门课有个学分,每门课有一门或没有直接先修课(若课程a是课程b的先修课即只有学完了课程a,才能学习课程b).一个学生要从这些课程里选择M门课程学习,问他能获得的最大学分是多少? 输入输出格式 输入格式: 第一行有两个整数N,M用空格隔开.(1<=N<=300,1<=M<=300) 接下来的N行