python 回溯法 子集树模板 系列 —— 6、排课问题
问题
某乡村小学有六个年级,每个年级有一个班,共六个班。
周一到周五,每天上6节课,共计30节课。
开设的课程
一年级:语(9)数(9)书(2)体(2)美(2)音(2)德(2)班(1)安(1)
二年级:语(9)数(9)书(2)体(2)美(2)音(2)德(2)班(1)安(1)
三年级:语(8)数(8)英(4)体(2)美(2)音(2)德(2)班(1)安(1)
四年级:语(8)数(8)英(4)体(2)美(2)音(2)德(2)班(1)安(1)
五年级:语(8)数(8)英(4)体(2)美(2)音(2)德(2)班(1)安(1)
六年级:语(8)数(8)英(4)体(2)美(2)音(2)德(2)班(1)安(1)
要求
- 各门课课时必须相符
- 周一最后一节课班会,周五最后一节课安全教育是固定的。
- 上午只能排语、数、英
- 全校只有两位音乐老师
- 三年级的数学不能排在周五上午第三节(三年级数学潘老师家里有事)
分析
将每一个(时间,空间)点对,作为一个元素。这些元素都具有各自的[状态1,状态2,状态3,状态4,状态5,状态6,状态7,状态8,状态9]共9个状态。
(时间,空间) --> 状态

一种状态对应一个课程。
对每一个元素,遍历相应的9种状态。
解的长度是固定的,30 * 6 的二维数组
套用子集树模板即可。
本问题只需要解决存在性。也就是说,只要找到一个符合要求的解就ok了。
此问题的本质就是,各(时,空)点对的取各自状态搭配的问题。
代码
'''排课问题'''
# 作者:hhh5460
# 写于:2017年5月30日22时33分
# 声明:此算法的版权归本人所有
m = 30 # 一周课时数(时间)
n = 6 # 全校班级数(空间)
o = 30 * 6 # 元素个数,即(时, 空)点对的个数
# 6个班开始的课程(状态空间)
a = [['语','数','书','体','美','音','德','班','安'], # 一年级
['语','数','书','体','美','音','德','班','安'], # 二年级
['语','数','英','体','美','音','德','班','安'], # 三年级
['语','数','英','体','美','音','德','班','安'], # 四年级
['语','数','英','体','美','音','德','班','安'], # 五年级
['语','数','英','体','美','音','德','班','安']] # 六年级
# 课时数
b = [[9,9,2,2,2,2,2,1,1],
[9,9,2,2,2,2,2,1,1],
[8,8,4,2,2,2,2,1,1],
[8,8,4,2,2,2,2,1,1],
[8,8,4,2,2,2,2,1,1],
[8,8,4,2,2,2,2,1,1]]
x = [[0 for _ in range(n)] for _ in range(m)] # 一个解,m*n 的二维数组
is_found = False # 结束所有递归标志!!!!!
# 冲突检测
def conflict(t, s):
'''只考虑刚刚排的x[t][s]'''
global m,n,o,a,b,x
# 一、各门课课时数必须相符(纵向看)
# 1.前面已经排的课时不能超
if [r[s] for r in x[:t+1]].count(x[t][s]) > b[s][a[s].index(x[t][s])]: # 黑科技,不要眼花!
return True
# 2.后面剩的课时不能不够
if [r[s] for r in x[:t+1]].count(x[t][s]) + (m-t-1) < b[s][a[s].index(x[t][s])]:
return True
# 二、周一最后一节课班会,周五最后一节课安全教育是固定的。
# 1.周一最后一节课班会
if x[t][s] == '班' and t != 5:
return True
# 2.周五最后一节课安全教育
if x[t][s] == '安' and t != 29:
return True
# 三、上午只能排语、数、英
if t % 6 in [0,1,2] and x[t][s] not in ['语','数','英']:
return True
# 四、只有两个音乐老师(横向看)
# 前面已经排的班级不能有3个及以上的班级同时上音乐课
if x[t][s] == '音' and x[t][:s+1].count('音') >= 3:
return True
# 五、三年级的数学不能排在周五上午第三节(三年级数学潘老师家里有事)
if x[t][s] == '数' and t==5*n+3-1:
return True
return False # 无冲突
# 套用子集树模板
def paike(t, s): # 到达(t,s)时空点对的位置
global m,n,o,a,b,x, is_found
if is_found: return # 结束所有递归
if t == m: # 超出最尾的元素
#print(x)
show(x) # 美化版
is_found = True # 只需找一个
else:
for i in a[s]: # 遍历第s个班级的对应的所有状态,不同的班级状态不同
x[t][s] = i
if not conflict(t, s): # 剪枝
ns = [s + 1, 0][s + 1 == n] # 行扫描方式
nt = [t, t + 1][s + 1 == n]
paike(nt, ns) # 去往(nt, ns)时空点对
# 可视化一个解x
def show(x):
import pprint
pprint.pprint(x[:6]) # 全校的周一课表
pprint.pprint(x[6:12]) # 全校的周二课表
pprint.pprint(x[12:18]) # 全校的周三课表
pprint.pprint(x[18:24]) # 全校的周四课表
pprint.pprint(x[24:]) # 全校的周五课表
# 测试
paike(0, 0) # 从时空点对(0,0)开始
效果图
正在运行中... ... 稍后奉上。
补:现在时间2017年6月1日7时40分,程序已运行34+时,还没有结果,囧!
之所以这么慢,其原因可能是递归太多了!
好吧,那只能等我以后将递归版本改为迭代版本,再运行看其结果如何了。
python 回溯法 子集树模板 系列 —— 6、排课问题的更多相关文章
- python 回溯法 子集树模板 系列 —— 18、马踏棋盘
问题 将马放到国际象棋的8*8棋盘board上的某个方格中,马按走棋规则进行移动,走遍棋盘上的64个方格,要求每个方格进入且只进入一次,找出一种可行的方案. 分析 说明:这个图是5*5的棋盘. 图片来 ...
- python 回溯法 子集树模板 系列 —— 17、找零问题
问题 有面额10元.5元.2元.1元的硬币,数量分别为3个.5个.7个.12个.现在需要给顾客找零16元,要求硬币的个数最少,应该如何找零?或者指出该问题无解. 分析 元素--状态空间分析大法:四种面 ...
- python 回溯法 子集树模板 系列 —— 16、爬楼梯
问题 某楼梯有n层台阶,每步只能走1级台阶,或2级台阶.从下向上爬楼梯,有多少种爬法? 分析 这个问题之前用分治法解决过.但是,这里我要用回溯法子集树模板解决它. 祭出元素-状态空间分析大法:每一步是 ...
- python 回溯法 子集树模板 系列 —— 15、总结
作者:hhh5460 时间:2017年6月3日 用回溯法子集树模板解决了这么多问题,这里总结一下使用回溯法子集树模板的步骤: 1.确定元素及其状态空间(精髓) 对每一个元素,遍历它的状态空间,其它的事 ...
- python 回溯法 子集树模板 系列 —— 14、最长公共子序列(LCS)
问题 输入 第1行:字符串A 第2行:字符串B (A,B的长度 <= 1000) 输出 输出最长的子序列,如果有多个,随意输出1个. 输入示例 belong cnblogs 输出示例 blog ...
- python 回溯法 子集树模板 系列 —— 10、m着色问题
问题 图的m-着色判定问题 给定无向连通图G和m种不同的颜色.用这些颜色为图G的各顶点着色,每个顶点着一种颜色,是否有一种着色法使G中任意相邻的2个顶点着不同颜色? 图的m-着色优化问题 若一个图最少 ...
- python 回溯法 子集树模板 系列 —— 9、旅行商问题(TSP)
问题 旅行商问题(Traveling Salesman Problem,TSP)是旅行商要到若干个城市旅行,各城市之间的费用是已知的,为了节省费用,旅行商决定从所在城市出发,到每个城市旅行一次后返回初 ...
- python 回溯法 子集树模板 系列 —— 8、图的遍历
问题 一个图: A --> B A --> C B --> C B --> D B --> E C --> A C --> D D --> C E -- ...
- python 回溯法 子集树模板 系列 —— 3、0-1背包问题
问题 给定N个物品和一个背包.物品i的重量是Wi,其价值位Vi ,背包的容量为C.问应该如何选择装入背包的物品,使得放入背包的物品的总价值为最大? 分析 显然,放入背包的物品,是N个物品的所有子集的其 ...
- python 回溯法 子集树模板 系列 —— 13、最佳作业调度问题
问题 给定 n 个作业,每一个作业都有两项子任务需要分别在两台机器上完成.每一个作业必须先由机器1 处理,然后由机器2处理. 试设计一个算法找出完成这n个任务的最佳调度,使其机器2完成各作业时间之和达 ...
随机推荐
- 关于win10下JDK环境变量的配置以及关于JDK的一些说明
一.JDK的下载和安装 这里提供32位和64位JDK的下载链接 百度网盘:https://pan.baidu.com/s/1xtiVOE2gPCvlGCTy0vfBaw 密码:c5m4 官网:ht ...
- Django组件扩展 总结
1. Form组件扩展: 验证用户输入 obj = Form(reuest,POST,request.FILES) if obj.is_valid(): obj.clean_data else: ob ...
- 简单的分页小demo
public class Demo { public static void main(String[] args) { Scanner sc = new Scanner(System.in); Sy ...
- Python笔记(四):异常处理机制与 open()
(一) 异常处理机制概述 就像日常生活中会遇到各种意外情况一样(例如:你可能考虑过如果中了500w该怎么做),代码运行过程中也会遇到这种意外情况,python提供了这么一种机制,处理意外情况(就像如 ...
- android dev概念快速入门
apk: android将源代码依赖库等经过编译后打包分发的应用. 打包详细过程如下: android-studio安装 由于google被qiang,需要制定proxy,可以使用sock,同时安装完 ...
- Mysql使用优化之处(转)
1 开启事务之前需要rollback 连接句柄.(清理垃圾)2 mysql_ping 失败,程序需要处理重连逻辑:3 mysql_query()执行的SQL语句是一个以‘/0’结尾的字符串,而mysq ...
- [IDEA_3] IDEA 配置 GitHub 并上传项目
0. 说明 参考 Git & GitHub 的安装配置 IDEA 配置 GitHub 并上传项目 1. 安装配置 Git & GitHub 参照 Git & GitHub 的安 ...
- Linux启动一个服务后,服务的某个文件所在的目录下出现类似:systemd-private.xxxxxx的目录
Linux的目录下面形如: [root@:vg_adn_tidbCkhsTest:172.31.17.203 /var/lib/mysql]#ll /tmp total drwxr root root ...
- php linux 环境搭建
Apache源于NCSAhttpd服务器,经过多次修改,成为世界上最流行的Web服务器软件之一.Apache取自“a patchy server”的读音,意思是充满补丁的服务器,因为它是自由软件,所以 ...
- SDN 期末作业验收
前言 SDN 期末作业验收我们是采用的参考场景一,我们在此场景的基础上来做负载均衡,下面是我们搭建的拓扑图 演示视频 https://pan.baidu.com/s/1htkKLPM 负载均衡程序 相 ...