• 输出最大选修学分问题


    关注 码龄 粉丝数 原力等级 -- 被采纳 被点赞 采纳率 mysterious coda 2024-05-12 14:18 采纳率: 33.3% 浏览 1 首页/ 编程语言 / 输出最大选修学分问题 c语言 学校开设了n门选修课程,每门课程的学分为ci,每个学生可选课程的数量不超过m门,学生选修了这些课程并考核通过后就能获得相应的学分,在选修课程中,有些课程可以直接选修,有些课程有一门直接先修课。 你的任务是为自己确定一个选课方案,在满足先修课优先的原则下,使得你能得到的学分最多,并判断该学分有没有达到最低学分的要求,假定课程之间不存在时间上的冲突。 相关知识 为了完成本关任务,你需要掌握: 1.课程先修关系用什么结构表示? 2.如何利用算法求出在先修课、总学分等约束条件下最大的选修学分? 课程先修关系用什么结构表示? 可以思考课程之间的先修关系用什么数据结构来保存,因为每门课程最多1门先修课,可以考虑树型结构,并且有多门课程没有直接先修课,因此模型就是一个森林。 如何利用算法求出在先修课、总学分等约束条件下最大的选修学分? 需要设计动态规划算法的状态转移方程,保证满足最优化原理,能正确求解最大选修学分,并输出。 编程要求 根据提示,在右侧编辑器补充代码,计算并输出选修课程的最大学分。 测试说明 平台会对你编写的代码进行测试: 输入第一行:n,m(课程门数,最大选修门数) 输入第二行:n门课程的学分数 输入其他行:课程先修关系(i,j) (i,j)表示i课程是j课程的先修课 测试输入: 10,6 3,1,2,5,2,4,4,1,5,2 1,2 1,3 1,4 3,5 3,6 7,8 7,9 7,10 预期输出: 最大学分:23 用C语言完成该题目,该题目的要求是先用树的遍历,然后再用动态规划求出想要的结果,不要用结构体,用数组就行 展开全部 收起 写回答 好问题 0 提建议 追加酬金 关注问题 微信扫一扫 点击复制链接 分享 邀请回答 编辑 收藏 删除 结题 收藏 举报 追加酬金 (90%的用户在追加酬金后获得了解决方案) 当前问题酬金 ¥ 0 (可追加 ¥500) ¥ 15¥ 20¥ 50¥ 100¥ 200 支付方式 扫码支付 二维码出错 点击刷新 支付金额 15 元 提供问题酬金的用户不参与问题酬金结算和分配 支付即为同意 《付费问题酬金结算规则》 结题 再想想 删除 再等等

    3条回答 默认 最新

    • 专家-皆知 2024-05-12 14:18
      关注

      使用动态规划求解选修最高学分。

      以上回复有部分引自免费微信小程序:皆我百晓生。 如问题尚未解决,还请稍待,如有疑问请回复进一步沟通。

      评论
      专家-皆知 回复 mysterious coda 2024-05-12 14:19

      要解决这个问题,我们可以将课程先修关系建模为一个邻接列表,然后使用拓扑排序来确保我们按照先修顺序选择课程。接下来,我们将使用动态规划来找到最大学分的选课组合。

      首先,我们需要创建一个二维数组adjacency_list来表示课程间的先修关系,其中adjacency_list[i]是一个整数数组,包含所有需要在课程i之前学习的课程索引。然后,定义一个一维数组dp用于存储动态规划状态,dp[i][j]表示前i个课程中选择j个课程时的最大学分。

      以下是完整的C语言代码实现:

      #include 
      #include 
      
      #define MAX_COURSES 100
      #define MAX_STUDENTS 100
      
      int adjacency_list[MAX_COURSES][MAX_COURSES];
      int dp[MAX_COURSES + 1][MAX_STUDENTS + 1];
      
      void add_edge(int from, int to) {
          adjacency_list[from][adjacency_list[from][0]++] = to;
      }
      
      int topological_sort(int n, int m) {
          int in_degree[MAX_COURSES] = {0};
          int i, j;
      
          for (i = 0; i < n; i++) {
              for (j = 0; j < adjacency_list[i][0]; j++) {
                  in_degree[adjacency_list[i][j]]++;
              }
          }
      
          int stack[MAX_COURSES], top = -1;
          int sorted_courses[MAX_COURSES];
          int num_sorted = 0;
      
          for (i = 0; i < n; i++) {
              if (in_degree[i] == 0) {
                  stack[++top] = i;
              }
          }
      
          while (top >= 0) {
              int cur_course = stack[top--];
              sorted_courses[num_sorted++] = cur_course;
      
              for (j = 0; j < adjacency_list[cur_course][0]; j++) {
                  in_degree[adjacency_list[cur_course][j]]--;
                  if (in_degree[adjacency_list[cur_course][j]] == 0) {
                      stack[++top] = adjacency_list[cur_course][j];
                  }
              }
          }
      
          return num_sorted <= m;
      }
      
      int max_score(int n, int m) {
          int i, j, k;
          int total_score = 0;
      
          for (i = 0; i < n; i++) {
              scanf("%d", &dp[i][0]);
              total_score += dp[i][0];
          }
      
          for (i = 1; i <= n; i++) {
              for (j = 1; j <= m; j++) {
                  dp[i][j] = dp[i - 1][j];
                  for (k = 0; k < adjacency_list[i - 1][0]; k++) {
                      if (j >= adjacency_list[i - 1][k]) {
                          dp[i][j] = max(dp[i][j], dp[adjacency_list[i - 1][k]][j - adjacency_list[i - 1][k]] + dp[i - 1][0]);
                      }
                  }
              }
          }
      
          return dp[n][m];
      }
      
      int main() {
          int n, m;
          scanf("%d %d", &n, &m);
      
          for (int i = 0; i < n; i++) {
              dp[i][0] = 0;
          }
      
          for (int i = 0; i < n; i++) {
              dp[0][i] = 0;
          }
      
          int from, to;
          for (int i = 0; i < n; i++) {
              scanf("%d", &dp[i][0]);
          }
      
          for (int i = 1; i < n; i++) {
              scanf("%d %d", &from, &to);
              add_edge(from - 1, to - 1);
          }
      
          if (!topological_sort(n, m)) {
              printf("无法选满%d门课程\n", m);
          } else {
              int max_score_result = max_score(n, m);
              printf("最大学分: %d\n", max_score_result);
          }
      
          return 0;
      }
      

      这个程序首先读取课程数量、最大选修门数、每门课程的学分以及课程先修关系。接着,它使用邻接列表构建先修关系,并进行拓扑排序检查是否可以选满指定的课程数量。如果可以,它调用max_score函数使用动态规划计算最大可能的学分。

      注意,这个代码没有处理错误输入的情况,实际应用中可能需要添加错误处理代码。此外,这个程序假定了输入的数据都是有效的,例如,所有的课程编号都在正确的范围内,并且不存在循环依赖的先修关系。

      回复
    • 笑面虎 2024-05-12 14:18
      关注

      以下内容由CHATGPT及笑面虎共同生成、有用望采纳:


      【您想要解决的问题】: 您想要解决的问题是如何使用C语言编写一个程序,该程序能够根据给定的课程数量、每门课程的学分、以及课程之间的先修关系,计算出一个学生在不超过最大选修课程数量限制的情况下,能够获得的最大学分,并判断这个学分是否达到了某个最低学分要求。

      【问题出现原因】: 这个问题出现的原因是,您需要处理一个具有先修课约束条件的选课问题,并且要求使用动态规划算法来找到最优解。同时,您需要考虑如何有效地表示课程之间的先修关系,以及如何设计算法的状态转移方程。

      【问题解决方案】: 为了解决这个问题,我们可以采取以下步骤:

      1. 使用数组来表示课程的学分和先修关系。
      2. 构建一个森林结构来表示课程之间的先修关系,因为可能有多个课程没有直接先修课。
      3. 对森林进行拓扑排序,以确定选修课程的一个可行顺序。
      4. 使用动态规划来计算在先修课和总学分约束条件下的最大选修学分。

      【提供代码】: 由于您要求不使用结构体,我们可以使用数组来表示课程的学分和先修关系。以下是一个简化的代码示例,用于计算最大学分:

      #include 
      
      #define MAXC 100
      #define MAXM 100
      
      int n, m;
      int scores[MAXC]; // 存储每门课程的学分
      int prerequisites[MAXC]; // 存储每门课程的先修课,如果没有先修课则为-1
      int dp[MAXM+1]; // 动态规划数组,dp[i]表示选修i门课程时的最大学分
      
      void findMaxCredits() {
          // 初始化dp数组
          for (int i = 0; i <= m; i++) {
              dp[i] = 0;
          }
      
          // 对课程进行拓扑排序
          // 这里需要一个栈或者队列来实现拓扑排序,代码略
      
          // 动态规划计算最大学分
          for (int i = 1; i <= n; i++) {
              for (int j = m; j > 0; j--) {
                  if (prerequisites[i-1] == -1 || j >= prerequisites[i-1] + 1) {
                      dp[j] = max(dp[j], dp[j-1] + scores[i-1]);
                  }
              }
          }
          printf("最大学分:%d\n", dp[m]);
      }
      
      int main() {
          // 读取输入
          // ...
      
          // 计算最大学分
          findMaxCredits();
      
          return 0;
      }
      

      【代码运行方式】: 您需要一个支持C语言的编译器,如GCC或Clang。将上述代码保存为.c文件,然后在命令行中使用编译器编译并运行程序。例如,如果您使用GCC,可以这样编译和运行代码:

      gcc -o course_selection course_selection.c
      ./course_selection
      

      【代码预期运行结果】: 代码将输出在满足先修课和最大选修课程数量限制下的最大学分。

      【推荐相关链接】:

      请注意,上述代码是一个简化的示例,实际的解决方案可能需要更详细的拓扑排序和动态规划实现。

      展开全部

      评论 编辑记录
    • Kwan的解忧杂货铺 Java领域优质创作者 2024-05-12 14:19
      关注

      下午好🌅🌅🌅
      本答案参考ChatGPT-3.5

      问题分析:

      本题是一个动态规划的问题,需要先根据给定的先修课关系构造一棵树,再采用动态规划算法求解最大选修学分。

      具体解决方案如下:

      1. 构建树

      将每门课程看做一个节点,若课程B是先修课程A的后修课程(即需要先修A才能修B),则在树中以A为父节点,B为子节点建立一条边。

      1. 动态规划

      定义状态:

      设dp[i][j]表示选取以节点i为根节点的子树中,最多选j门课程得到的最大学分。因为一个节点必须选或不选,因此状态j的范围为0~m。

      状态转移方程:

      对于节点i,分为两种情况讨论:

      • 当节点i不选时,dp[i][j] = dp[i-1][j]
      • 当节点i选时,dp[i][j] = dp[i-1][j-1] + ci

      其中,ci为第i个节点对应的课程学分。

      在状态转移方程中,dp[i-1][j]和dp[i-1][j-1]表示为前一个节点的状态,两个状态的中较大值即为当前状态的最大值。因此状态转移方程可以简写为

      dp[i][j] = max(dp[i-1][j], dp[i-1][j-1] + ci)

      求解:

      对于节点i,先求解dp[i][0]~dp[i][m]中的最大值,然后将这些最大值累加即可得到以节点i为根节点的子树中,最多选m门课程得到的最大学分。

      最终结果为所有子树中最大的学分和。

      1. 代码实现

      以下是用C语言实现的代码:

      展开全部

      评论
    编辑
    预览

    报告相同问题?

  • 相关阅读:
    MySQL高级篇知识点——索引优化与查询优化
    IDEA(日常操作技巧记录)
    【转存】Linux环境RabbitMq搭建部署
    猿创征文|Hadoop大数据技术
    操作系统对内存的管理:分配与回收,虚拟内存,内存容量的扩充,内存保护,补充(程序相关:链接方式、装入方式)
    为什么Transformer模型中使用Layer Normalization(Layer Norm)而不是Batch Normalization(BN)
    LeetCode 104. 二叉树的最大深度
    1235. 规划兼职工作 动态规划
    联盟营销最佳实践:提高联盟计划的投资回报率
    生草也叫草生
  • 原文地址:https://ask.csdn.net/questions/8102220