/blob/master/example_input_data.txt
生成示例遵守的最優先規則應該是符合生活中的實際情況。
除非特別指出,以下部門的特點標籤
和學生的興趣標籤
統稱為標籤
,部門的常規活動時間段
和學生空閒時間段
統稱為時間段
,工作日
指周一至周五,週末
指週六和週日
。
標籤生成
我們將用於生成的標籤全集數量限制在了 30 個,定義如下:
const string tags = ;
這些標籤在定義時都應該是較為寬泛的內容,否則如果乙個標籤太過細化,例如考研講座
,將導致標籤沒有多部門復用的意義。
我們設定部門的特點標籤為 2 到 4 個,學生的興趣標籤為 8 到 12 個。
雖然以上的標籤已經較為寬泛,但有一些標籤不太可能同時是某乙個部門的,例如liquor
和basketball
,為了避免這樣的情況,我們建立了乙個圖,每乙個標籤是乙個節點,兩個節點若有聯絡(即可能同時是某乙個部門的),則它們之間存在一條雙向邊。每個部門選取的所有標籤應當兩兩間存在一條邊。
部門選取興趣標籤時,先隨機選取乙個興趣標籤,然後再繼續隨機,並檢測是否符合上述關係。
學生興趣標籤隨機選取即可。
學生空閒時間段生成
我們把學生工作日的空閒時間段數量設定為5到8個,在較為固定的八大塊時間內選取,定義如下:
一二節課
三四節課
午飯及午休
五六節課
七八節課
晚飯時間
九到十一節課
晚上下課後
8:00~10:10
10:10~12:00
12:00~14:00
14:00~15:45
15:45~17:30
17:30~19:00
19:00~21:30
21:30~23:30
const string student_time_period = ;
上述字串陣列這麼設定是因為我們把這八個時間段再分為三個塊:
按 3:2:1 的可能性隨機分配到這三個塊上,再隨機選取具體的時間段。
學生週末的空閒時間段和工作日的類似,把空閒時間段數量設定為 13 到 16 個,也在較為固定的八大塊時間內選取,但分為兩個塊:
按 3:1 的可能性隨機分配到這兩個塊上,再隨機選取具體的時間段。
部門常規活動時間段生成
設定部門常規活動時間段數量為 2 到 3 個,一天最多乙個,按 1:3 的可能性隨機分配到工作日和週末,再隨機生成工作日或週末中某一天的某一段時間作為常規活動時間段。
隨機設定活動的起始時間為 8:00~21:00 中 30 分鐘整數倍時間點,活動時間長度的選取方式如下:
部門的常規活動一般可能有:
活動名稱
可能的時間長度(min)
每週次數
例會(或類似的固定活動)
30 45 60 75 90
一次週末聚餐(或類似的偏向週末的活動)
90 120
零次到一次
學習、講座(或類似的偏向工作日的活動)
60 90 120
零次到兩次
綜上,部門的常規活動每週約2到3次,30、45、75 分鐘的活動大概每週零次到一次,60、90、120 分鐘的活動佔據剩下的次數。定義如下:
const int department_time_period = ;
學生部門意願生成
現實生活中,當我們面對很多部門納新安利時,會優先選取有興趣、自己空閒時間較符合這個部門活動時間的,但有的人會害怕這些部門太熱門(我們假設學生不知道任何部門的熱門程度),又不想空手而歸,因此報名一些其他部門。也有的人就是喜歡獵奇,報名了喜歡的部門後同樣報名一些其他部門。
有的人比較奇怪,不想報部門還填寫申請表(部門意願空缺),這部分人設定為0到10個。
剩下的有部門意願的人中,學生a的總部門意願數量為隨機0到5個,將學生a的空閒時間段與所有部門常規活動時間段進行比較,若有許多部門的常規活動學生a都有空,則將學生a的標籤與這些部門的標籤進行比較,按重合數量排序,取排序後的部門列表前隨機0到3個作為部門意願(優先選取有興趣、時間符合)。總部門意願數量減去前面已經新增的部門意願數量的差若為正數,隨機選取差額部門作為部門意願(不想空手而歸與獵奇)。
其他其他的 部員數量限制、部門號、學生號 使用簡單的隨機或遞增即可。
部門和學生建立為兩個類(僅列出重要成員):
class department
;class student
;
我們使用rapidjson
來處理 json。
我們稱乙個部門的常規活動時間學生a都有空
為時間符合
,稱乙個部門的特色標籤和學生a的興趣標籤重複數量
為標籤符合
。
匹配演算法建立乙個類(僅列出重要成員):
class matcher
;
從input_data.txt
匯入解析後,用department department[department_size]
和student student[student_size]
分別儲存所有的部門與學生資訊。
匹配演算法目的是盡量讓乙個部門收取盡可能多的學生。
有學生申請的部門的申請列表中,將學生先按時間符合排序,再按標籤符合排序,取所有可取的,且少於部員數量限制的學生,加入matched
陣列,否則再將申請列表剩下的學生按時間符合排序,取所有可取的,且少於部員數量限制的學生,加入matched
陣列。
做完上述步驟後,未被分配到學生的部門加入unluckydepartments
陣列,未被部門選中的學生加入unluckystudents
陣列。
最後將unluckystudents
陣列、unluckydepartments
陣列、matched
陣列phrase
並輸出到output_data.txt
。
stdafx.h
中按照系統標頭檔案(例如vector
)、外部標頭檔案(json處理,例如rapidjson/document.h
)、自身class
標頭檔案(例如mockdatagenerator.h
)排序,在整個專案中統一引用
大括號換行風格,更加清晰易讀
允許if
後只有一行**時不使用大括號
過長的一行應當換行以適合閱讀
函式中新增適當空行以分清結構
適當注釋
根據我們上面生成的示例資料生成演算法和匹配演算法執行多次,有如下結果分析:
生成演算法還算符合預期,部門的標籤是有關聯的,不會有熱衷泡茶的電競部門出現。學生和部門的時間段也大致模擬真實情況,週末較多,學生空閒時間較固定,部門活動時間長度較固定。重點在於學生部門意願,現實生活中我們一般不了解想要報名的部門的常規活動時間段,只是按興趣標籤來報,但這裡我們假設學生可以閱覽所有部門的常規活動時間段,並相應做出選擇,這更有利於精確匹配。
匹配結果中,比較不錯的是幾乎不會有未被分配的部門出現,但未被分配的學生大概在130-160個左右,這比較尷尬。原因在於,學生的空閒時間都挺多的,可能有許多學生填寫同一些部門,但這些部門限制只收10-15個,這些學生被收取後,剩下的也選這些部門的學生就被拒之門外,又因為他們填寫的其他「冷門」部門較少,所以就被扔進了unluckystudents
。因此,想要改進的話應該還是要從兩個演算法入手,例如匹配要求放寬(時間不完全匹配也行),生成部門意願時對時間符合和標籤符合按某個權值相加,放寬時間符合要求。
這次作業遇到國慶,我去浪了而對友在忙別的事,所以沒有盡早開始做,後來加班加點,效率又不高瘋狂寫bug。對友是 acm 的,所以很多概念與演算法都是理解、思考、實現迅速,這大大促進了我們的程序。所以要特別感謝對友,承擔起了大部分的演算法實現重任,才有辦法強行完成。
軟體工程實踐2017第二次作業
github鏈結 1 拿到題目後,覺得這題目和八皇后的題挺像的,都是行列衝突問題,因此覺得可以通過將乙個99的數獨圖變成9個33的圖,對每張33的圖進行數字的填充,例如先將1填入9張小圖中。按以上思路寫完程式後,在行數下移的同時還需要在對應的圖中找到下乙個數填入的位址,產生了可能會跳過某一行填入數值...
軟體工程實踐2017第二次作業
github連線 利用程式隨機構造出n個已解答的數獨棋盤 輸入 數獨棋盤題目個數n 0 n 1000000 輸出 隨機生成n個不重複的已解答完畢的數獨棋盤,並輸出到sudoku.txt中。參考 其實看了這個 以後,我深受影響,把自己的設想都推翻了,總覺得自己的方法不太好,想學習這個方法。我認真理解了...
軟體工程實踐2017第二次作業
預估耗時 分鐘 實際耗時 分鐘 planning 計畫20 10 estimate 估計這個任務需要多少時間 2010 development 開發375 465 analysis 需求分析 包括學習新技術 3030 design spec 生成設計文件 1010 design review 設計複...