【问题标题】:What's the most efficient way to write a course timetabling system in PHP?用 PHP 编写课程时间表系统的最有效方法是什么?
【发布时间】:2011-11-06 20:23:25
【问题描述】:

问题: 给定一组必修课和选修课,每门课程都只在特定的时间段(有 7 个时间段)提供,生成所有可能的时间表。

例子:

必修课:

  • MAT101 - 1、2、5
  • HIS102 - 2、4、6
  • ENG105 - 3、6、7

还有选修课:

  • LIT103 - 3、4、6
  • CHE101 - 7、1、2
  • BIO101 - 5、4、7
  • MAT201 - 6、5、1
  • ANT201 - 1

(并非每门选修课都必须包含在时间表中)

可能的解决方案之一是:

  1. MAT101 [强制性]
  2. HIS102 [强制性]
  3. LIT103
  4. 生物101
  5. MAT201
  6. ENG105 [强制性]
  7. CHE101

用 PHP 编写它最有效的方法是什么?

我目前正在尝试开发一种蛮力解决方案,但这是一项非常繁琐的任务,我正在寻找更有效的方法来完成它。我发现这是一个 NP 完全问题,并搜索了有助于解决此类问题的 PHP 类,但恐怕目前没有这样的类。

【问题讨论】:

  • 听起来你真正需要的是一种有效的算法来解决这类问题(不管是什么语言)。您是否尝试过查看其他语言,或完全在特定语言之外寻找解决方案?一旦有了解决方案(算法),您很可能能够将其移植到 PHP 代码中。
  • 是的,有一段时间了。 Java 有 Drools planner - 一个专门解决 NP 问题的框架,但是虽然它是开源的,但我认为我没有能力也没有时间自己移植如此庞大而复杂的框架。还有约束编程对解决此类问题非常有帮助,但是我找不到任何 PHP 的约束编程库。

标签: php scheduling np-complete


【解决方案1】:

首先我同意 Bryan 的观点,您首先需要对问题有一个全面的了解,然后对于互联网上的算法有一定的了解。

你说不是每门选修课都必须包括,这意味着这个模式是唯一被接受的:

obc x x x x x x

其中 obc 是必修课,x 是必修课或可选课。顺序当然不重要。

如果你有 N 门必修课和 M 门选修课(显然 N+M>7 或 N+M=7),那么你只能有 N 种接受的上述模式。

那么你必须找到所有不同的此类时间表:

X X X X X X(6 门课程)

这里的顺序无关紧要,不允许重复,所以你需要(N+M)中的6个组合,这将使得:

(N+M)!/[6!(N+M-6)!] = K different such timetables.

那么 7 门课程的所有不同时间表将是:

K+K+...+K(N次)=N*K

(仔细检查是否正确,今天真的很累,否则会提示一些代码)。

我希望这能有所帮助。

【讨论】:

    【解决方案2】:

    问题:

    问题:给定一组必修课和选修课,每个是 仅在某些时隙可用(有 7 个时隙)生成 所有可能的时间表。

    这里的关键是生成所有可能的时间表。这样做很简单,但是以任何方式切片都需要指数级的时间,因为您实际上是在列出整个搜索空间(可能性)。

    这将是递归的,并采用对的列表,对的第一个是一个时隙,对的第二个元素是可以填充时隙的可能类的列表。数据结构如下所示:

    必修课:

    • 1 - MAT101、CHE101、MAT201、ANT201
    • 2 - MAT101、HIS102、CHE101
    • 3 - ENG105, LIT103

    等等。需要加粗的课程。 它还需要一个已经被该方法的先前递归调用选择的课程列表。

    函数会

    • 检查可能性列表(如上所述)是否与已选择的课程列表一起包含所有必修课程。如果没有,请返回。
    • 选择第一个可用的时间段(称为 myPick),然后
    • 对于每个可能填满该时隙的类(称为 currentClass),
      • 如果此方法在其第一个参数中只指定了 1 个时隙,
        • 打印已选择的类列表(作为参数给出)。
        • 打印“$currentClass $myPick\n”,
        • 打印一个额外的换行符来分隔列表。返回。
      • 否则递归调用该方法,在该方法中您将尚未选择的时隙列表(作为参数给出的时隙列表减去您在步骤 2 中刚刚选择的时隙列表)提供给它,除了每种可能性时隙列表中删除了您打印的类。递归调用的第二个参数应该是给这个调用实例的已经选择的类列表,其中添加了 (<currentClass,myPick>)。

    这应该让你开始。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-23
      • 1970-01-01
      • 1970-01-01
      • 2022-01-24
      • 1970-01-01
      相关资源
      最近更新 更多