当前位置:首页 > 其他 > 1997年CTSC选课问题(洛谷P2014)解题全解析:动态规划与树形结构实战

1997年CTSC选课问题(洛谷P2014)解题全解析:动态规划与树形结构实战

17小时前

1997年CTSC选课问题(洛谷P2014)解题全解析:动态规划与树形结构实战 CTSC选课 洛谷P2014 动态规划 树形结构 分组背包 第1张

一、题目解读

CTSC选课问题(洛谷P2014)要求在一个具有依赖关系的课程树中,选择m门课程以获得最大总学分。课程之间存在先修关系,即某些课程必须在其前置课程被选修后才能选择。题目核心在于如何高效处理依赖关系并求解最优组合,属于典型的动态规划应用场景。

二、解题思路

采用动态规划+树形结构求解:

1. 树形结构建模:使用vector构建课程树,每门课程作为节点存储其子节点(后续课程)。

2. 虚拟根节点:添加节点0作为虚拟根,将所有无前置课程的节点挂在其下,确保DP从单一入口开始。

3. 动态规划状态定义:dp[u][m]表示以u为根节点选m门课的最大学分。

4. 分组背包优化:对每个子树进行分组背包DP,倒序枚举避免重复计算,确保每门课仅被选一次。

5. 关键逻辑:必须选修当前课程才能选其子课程(虚拟根除外),通过逆向更新实现。

三、解题步骤

1. 输入与构建课程树:读入n门课程,每门课程的前置节点pre与学分credit,将课程i加入pre的子节点列表。

2. 虚拟根初始化:节点0作为根,所有无前置课程的节点挂在其下。

3. 深度优先搜索(DFS):从根节点0开始递归,遍历每个子树:

    递归处理子节点v,更新v的子树dp值。

    对当前节点u:

        倒序枚举m门课的组合,通过分组背包合并子树v的最优解。

        若u非虚拟根,强制选择u后更新剩余学分组合的dp值。

4. 输出结果:最终答案存储在dp[0][m],即从虚拟根选m门课的最大学分。

四、代码与注释

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

const int MAXN = 310;
vector<int> tree[MAXN];  // 课程树结构
int credit[MAXN];        // 课程学分
int dp[MAXN][MAXN];      // dp[u][m]表示以u为根选m门课的最大学分
int n, m;

// 深度优先搜索+动态规划
void dfs(int u) {
    for(int v : tree[u]) {  // 遍历所有子节点
        dfs(v);
        // 分组背包过程(倒序枚举)
        for(int j = m; j >= 0; j--) {
            for(int k = 1; k <= j; k++) {
                dp[u][j] = max(dp[u][j], dp[u][j-k] + dp[v][k]);  // 合并子树最优解
            }
        }
    }
    // 必须选当前课程才能选其子课程(虚拟根0除外)
    if(u!= 0) {
        for(int j = m; j >= 1; j--) {
            dp[u][j] = dp[u][j-1] + credit[u];  // 强制选u后更新学分
        }
    }
}

int main() {
    cin >> n >> m;  // 课程数n,需选m门
    // 构建课程树,0为虚拟根节点
    for(int i = 1; i <= n; i++) {
        int pre;
        cin >> pre >> credit[i];
        tree[pre].push_back(i);  // 前置课程pre的子节点为i
    }
    
    dfs(0);  // 从虚拟根开始DP
    cout << dp[0][m] << endl;  // 输出最优学分
    return 0;
}

五、总结

本文通过动态规划与树形结构的结合,巧妙解决了CTSC选课中的依赖关系问题。关键在于利用虚拟根节点统一入口,分组背包优化组合选择,避免了复杂搜索。该思路可扩展至其他树形依赖优化场景,如项目调度、资源分配等。建议读者结合代码注释深入理解状态转移逻辑,并尝试优化时间复杂度(如记忆化搜索迭代优化)


原创内容 转载请注明出处

分享给朋友:

相关文章

NOIP2005 普及组 洛谷P1408 背包问题的空间优化技巧与实战应用

NOIP2005 普及组 洛谷P1408 背包问题的空间优化技巧与实战应用

题目重解想象你是一名药师,有t分钟在山上采集m种草药。每种草药需要time分钟采集,价值为num。这就像考试时分配时间做题,要选择收益最大的题目组合。题目要求计算在规定时间内能获得的最大草药价值。解题...

【动态规划入门】力扣509题:斐波那契数列的经典解法与优化思路

【动态规划入门】力扣509题:斐波那契数列的经典解法与优化思路

题目解读‌斐波那契数列是一个经典的数学问题,在计算机科学中常被用作算法教学的入门案例。这个神奇的数列从0和1开始,后续每个数字都是前两个数字之和。题目要求我们计算第n个斐波那契数,看似简单的问题背后却...

CSP-J 2019纪念品题解(洛谷P5662):动态规划+完全背包问题的实战应用

CSP-J 2019纪念品题解(洛谷P5662):动态规划+完全背包问题的实战应用

一、题目解读2019年CSP-J的“纪念品”问题(对应洛谷P5662)要求玩家在T天内通过买卖纪念品最大化金币收益。每天可交易N种商品,需计算最优策略下的最终金币数。题目强调动态规划思维与资源分配优化...

CSP-J方格取数题解|动态规划解法|洛谷P7074代码解析

CSP-J方格取数题解|动态规划解法|洛谷P7074代码解析

一、题目解读题目要求在一个n×m的网格中,从左上角到右下角选择一条路径,路径上的数字可重复取用,求取数之和的最大值。路径限制为仅能向右或向下移动。需注意路径的灵活性与重复取数的可能性,传统单向动态规划...

NOIP 2008火柴棒等式题解(C++代码实现)  动态规划与枚举算法详解

NOIP 2008火柴棒等式题解(C++代码实现) 动态规划与枚举算法详解

一、题目解读火柴棒等式问题(NOIP 2008,洛谷P1149)要求使用给定数量的火柴棒,构造形如 A + B = C 的等式,其中A、B、C均为整数,且火柴棒总数恰好等于输入值。需统计符合条件的等式...

洛谷P4551题解题报告:图论与Trie树优化异或路径问题的实战解析

洛谷P4551题解题报告:图论与Trie树优化异或路径问题的实战解析

一、题目解读洛谷P4551题要求在一个无向图中,寻找任意两点路径权值异或后的最大值。题目输入为图的边信息(点数n和n-1条边),每条边包含起点、终点及权值。需输出所有路径中权值异或的最大值。问题核心在...

发表评论

访客

看不清,换一张

◎欢迎参与讨论,请在这里发表您的看法和观点。