You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用R枚举无冲突必修课程表的所有可行方案?

用R高效枚举无时间冲突的选课方案

问题背景

给定四门必修课程的时段开设数据,需找出所有无时间冲突的选课组合(即每门课选一个时段,且所有时段不重复)。需避免嵌套循环这类暴力枚举方法的低效问题,尤其当课程/时段数量增加时(如8门课对应8个时段,暴力枚举的计算量为8^8,难以承受)。

给定的课程开设数据:

class_offerings <- tibble::tribble(
  ~time,   ~class1,    ~class2,    ~class3,    ~class4,
   "8:00",   1,          0,          0,          0,
   "9:00",   0,          0,          0,          1,
   "10:00",  0,          0,          1,          1,
   "11:00",  0,          1,          0,          1,
   "12:00",  1,          0,          0,          1,
  )

方法一:组合生成+过滤(适合小规模场景)

先提取每门课的可选时段,再生成所有可能组合,最后过滤出时段无重复的有效方案。

代码实现

library(tibble)
library(dplyr)
library(purrr)

# 提取每门课的可选时段列表
class_options <- class_offerings %>%
  select(-time) %>%
  map(~ class_offerings$time[.x == 1])

# 生成所有可能的选课组合,并过滤无冲突方案
valid_schedules <- cross(class_options, .name_repair = "minimal") %>%
  map_dfr(as_tibble) %>%
  rowwise() %>%
  filter(n_distinct(c_across(everything())) == ncol(.)) %>%
  ungroup()

# 查看结果
valid_schedules

方法二:二分图完美匹配(高效适配大规模场景)

将问题转化为二分图完美匹配问题:左侧节点为课程,右侧节点为时段,课程与可选时段之间连边。我们需要找到所有匹配方式,使得每门课匹配唯一时段,且每个时段仅被一门课占用。这种方法的时间复杂度远低于暴力枚举,适合课程/时段数量较多的场景。

代码实现

library(igraph)
library(tibble)
library(dplyr)
library(purrr)

# 构建二分图
# 定义节点:课程(class1-class4) + 时段(8:00-12:00)
nodes <- c(colnames(class_offerings)[-1], class_offerings$time)
# 定义边:课程到其可选时段的连接
edges <- class_offerings %>%
  pivot_longer(-time, names_to = "class", values_to = "offered") %>%
  filter(offered == 1) %>%
  select(class, time) %>%
  as.matrix()

# 创建二分图对象
g <- graph_from_edgelist(edges, directed = FALSE)
V(g)$type <- c(rep(TRUE, 4), rep(FALSE, 5)) # 标记课程节点(TRUE)和时段节点(FALSE)

# 找出所有完美匹配
all_matches <- all_simple_matching(g, type = "all")

# 将匹配结果转换为选课表格式
valid_schedules_graph <- map_dfr(all_matches, function(match) {
  match_df <- as.data.frame(match) %>%
    rename(class = from, time = to) %>%
    filter(class %in% colnames(class_offerings)[-1]) %>%
    arrange(class)
  tibble(
    class1 = match_df$time[match_df$class == "class1"],
    class2 = match_df$time[match_df$class == "class2"],
    class3 = match_df$time[match_df$class == "class3"],
    class4 = match_df$time[match_df$class == "class4"]
  )
})

# 查看结果
valid_schedules_graph

方法对比

  • 组合生成+过滤:代码简洁直观,适合课程数较少(如4门)的场景,但本质仍是枚举所有可能,课程数增加时计算量会快速上升。
  • 二分图匹配:基于图论算法,时间复杂度为多项式级(远低于暴力枚举的指数级),当课程/时段数量增加到8门及以上时,优势极为明显。

内容的提问来源于stack exchange,提问作者kenmore17

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 06:35:22