【题解】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\)是一个组,在其中选取不超过\(1\)个元素\(c_i\)加入背包。将当前枚举到的组作为阶段

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

Code

#include <cstdio>
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <vector>
#define maxn 305
#define maxm 305
using namespace std;
typedef long long ll;

int n,m;
vector<int> son[maxn];
int prt[maxn];
int pnt[maxn];
int dp[maxn][maxm];

void DP(int u)
{
    for(register int i=0;i<son[u].size();++i)//阶段,选取了第几组
    {
        int v=son[u][i];
        DP(v);
        for(register int t=m;t>=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

时间: 2024-08-30 15:14:10

【题解】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

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_

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$

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-

树形DP 洛谷P2014 选课

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

P2014 选课 - 树形DP[树形背包DP]

P2014 选课 传送门 思路: 树形背包DP模型,\(f[i,j]\)表示以\(i\)为根的子树中,选了\(j\)门课的最大学分.树形DP常以子树\(i\)为阶段.树形背包DP相当于树上分组背包DP.\(f[u,j]=max\{f[u,j],f[u,j-k]+f[v,k]~|~v\in~son(u)\}\).我们枚举从u的子树v中选的课数k,将\(f[v,k]\)作为获得的价值加到\(f[u,j-k]\)得到\(f[u,j]\).注意到当前子树根节点u是必须选的,所以要从\(f[u,j-1]\

题解 luogu P1850 【换教室】

题解 luogu P1850 [换教室] 时间:2019.8.6 一晚上(约 3.5h 写完) 题目描述 对于刚上大学的牛牛来说,他面临的第一个问题是如何根据实际情况申请合适的课程. 在可以选择的课程中,有 \(2n\) 节课程安排在 \(n\) 个时间段上.在第 \(i\)(\(1 \leq i \leq n\))个时间段上,两节内容相同的课程同时在不同的地点进行,其中,牛牛预先被安排在教室 \(c_i\) 上课,而另一节课程在教室 \(d_i\) 进行. 在不提交任何申请的情况下,学生们需要