同學畢業設計搞的是乙個排課系統,具體功能就給課程安排教室和時間。排課演算法是有一定難度的,很多老師說過,至今也沒有完美的排課演算法,的確,排課,是乙個五維交叉的複雜體系:時間、課程、教室、班級、學生。乙個排好的課表至少要保證以下幾點原則:
乙個教師同一時間只上一門他要教的課
乙個班級同一時間只上一門他要上的課
乙個教室同一時間只上一門課
拿到這個問題,剛開始覺得簡單,後來仔細分析後,發現難度相當大。關鍵是其複雜度太高,對待這種問題,我選擇排除法。也就是先列出可能的各種組合,再依據約束條件進行排除,最後留下的結果即是所求。
利用power designer來資料建模。
首先是建立教師、班級、課程表,因為他們是主體。並建立相關的關係對映表:
這五張表都是要作為輸入資料提交給自動排課系統的。
分配的主體還包括時間和地點,也就是上課時段和教室,由於系統要滿足三點原則,所以,需要將五維關係進行關聯,也就是教室和時間、教師和時間、班級和時間進行關係對映:
上圖中,教室表、教師表、班級表、上課時段表都是系統的輸入資料。而他們之間的關係對映表:room_time_map、class_time_map、teacher_time_map則是系統在執行中使用的表,系統就是靠他們完成前面提到的三個排除原則的,在系統執行之前,它們是空的。執行開始之後,每當系統要為一門課程分配教室時,都要檢查這三個對映表,看是否已經有相關的記錄。舉個例子:當系統要為語文課分配某個時間和某個教室時它首先要看class_time_map,看看上語文課的這個班級是否在同一時間已經有課,如果有則不分配這個時間。同理對教室,和教師。
篩選條件準備好之後,開始構造課程表,準確說是預排課程表,這個課程表包括各種可能:
它是教室表、上課時段、班級課程對應表、教師課程對應表的連線組合,只進行了乙個初步篩選,就是每條記錄中,的班級上的課程與教師上的課程必須是相同的。sql如下:
1在輸入10個班級、6位教師、5個教室、5門課程、15個上課時段(5 天 × 3 時段/每天)的情況下共有3450條記錄產生。select
2cc.courseid,
3r.roomid,
4cc.classid,
5tc.teacherid,
6t.timeid
7into
8tempplans
9from
10 dbo.class_course_map as
cc,11 dbo.teacher_course_map as
tc,12 dbo.times as
t,13 dbo.rooms asr14
where
15 cc.courseid = tc.courseid
在構造乙個最終課程表,結構與預排課程表相同,用來放最終結果。所有預排課程表中的記錄只要滿足篩選條件都要插入到此表。
下面就要對3450條記錄進行篩選了,篩選之前還有乙個問題必須考慮,那就是這3450條記錄中有很多記錄可能出現如下情況:乙個班級在不同時間內上同一門課程若干次,而不是一次。系統是假定每門課程每個班級只上一次的(這可能有悖常理,稍後討論)。所以有必要再構造乙個表進行條件篩選,此表稱之為班級課程記錄表:
每當系統為乙個班級分配好一門課程時,都會將班級、課程號記錄再此表內,將來再插入記錄時便可以檢查改表,看是否以為該班分配了該課,避免重複。
下面就可以進行最後的執行了,系統將對預排課程表逐條檢查,看其是否滿足刪除條件:也就是看room_time_map、class_time_map、teacher_time_map、class_course_rec_map中是否已經有此記錄,如果有,略過;如果沒有證明可以排課,則將其新增到最終的課程表;最後將這條記錄從預排表中刪除。
sql如下:
1最終的結果條數應該與class_course_map中的條數是一致的,因為我們假設每個課程每個班只上一次。經檢測,實現了預想的效果,只是系統會盡少地完成安排,也就是說,系統會使用盡量少的教室安排課程,5個教室,只使用了3個。當然這些可以通過增加篩選條件加以避免。總的排課策略是對的。/*check the data one by one*/2
34while (select
count(*) from dbo.tempplans) >05
begin67
declare
@course
int,@room
int,@class
int,@teacher
int,@time
int8
select
top1
@course
=courseid, @room
=roomid, @class
=classid, @teacher
=teacherid, @time
=timeid
9from
dbo.tempplans
1011
declare
@classok
int,@teacherok
int,@roomok
int,@classrecok
int12
select
@classok
=count(*) from dbo.class_time_map where classid=
@class
and timeid=
@time
1314
select
@classrecok
=count(*) from dbo.class_course_rec_map where classid=
@class
and courseid=
@course
1516
select
@teacherok
=count(*) from dbo.teacher_time_map where teacherid=
@teacher
and timeid=
@time
1718
select
@roomok
=count(*) from dbo.room_time_map where roomid=
@room
and timeid=
@time
1920
if@classok
+@teacherok
+@roomok
+@classrecok=0
21begin
22insert
into dbo.class_time_map values(@time,@class)23
insert
into dbo.class_course_rec_map values(@class,@course)24
insert
into dbo.teacher_time_map values(@teacher,@time)25
insert
into dbo.room_time_map values(@room,@time)26
insert
into dbo.plans values(@course,@room,@class,@teacher,@time)27
end28
29delete
from
dbo.tempplans
30where courseid=
@course
and roomid=
@room
and classid=
@class
and teacherid=
@teacher
and timeid=
@time
3132
33end
文章最後解決前面提到的乙個問題:系統假設每門課程,每個班只上一次,這完全不滿足現實需要。例如,大學的英語,每週要上三次之多。其實這個很好解決,可以把英語看作三個不同的課程,命名為英語1、英語2、英語3,這樣對於上課多於一次的課程只要修改輸入表:課程、班級課程對應表、教室課程對應表就可以了,並不需要修改系統。
用shell 實現自動ftp的乙個例項
bin bash echo echo cintel ftp test tool echo please input hostip c read hostip echo please input username c read username echo please input password c...
乙個簡單功能的SQL 實現
1.假設有一張表示cj表 name subject result 張三 語文 80張三 數學 90張三 物理 85李四 語文 85李四 數學 92李四 物理 89要求查詢結果 姓名 語文 數學 物理 張三 80 90 85李四 85 92 89 建立cj表sql create table cj id...
乙個簡單功能的SQL 實現
1.假設有一張表示cj表 name subject result 張三 語文 80張三 數學 90張三 物理 85李四 語文 85李四 數學 92李四 物理 89要求查詢結果 姓名 語文 數學 物理 張三 80 90 85李四 85 92 89 建立cj表sql create table cj id...