本章目標理解什麼是互相衝突的時段與可行排程
用 Python 建立可重現的區間排程與加權排程流程
把會議、訪談與外勤安排轉成可驗證的時間與效益選擇問題
情境與限制情境:你有一串會議、訪談、外勤拜訪或交件時段,但其中不少會彼此撞期,必須挑出一組真的排得進一天行程的工作
輸入:每個任務的名稱、開始時間、結束時間,以及可選的效益值
輸出:互不衝突的任務清單、最高總效益的任務清單,以及可選的衝突配對資訊
限制:任務可能未先排序,且需要清楚定義「剛好銜接」是否算衝突,並處理效益排序與回溯還原
可重現規則本章程式碼位置:
examples/ch06/本章核心模組:
examples/ch06/scheduling.py測試:
pytest -q tests/test_ch06_scheduling_and_allocation.py典型用途:會議排程、拜訪安排、設備借用、工單時段配置
從撞期任務到可執行安排¶
本章會把「今天事情很多,但時間不夠」這類問題轉成區間排程。第一步先用貪婪法找出一組互不衝突、數量最多且可重現的任務安排。
但真實工作裡,不是每件事的重要性都一樣。有些會議可以改期,有些拜訪卻直接影響成交或簽核。因此本章再往前走一步,加入加權排程,讓任務除了時間之外,還能帶有效益值,最後求出總效益最高的一組可行安排。
另外,我們也保留衝突檢查函式,讓你在排程之前就能知道哪些任務彼此重疊,方便做人工協調或規則調整。
什麼時候用哪一種排程¶
實務上,很多人會直接問:「到底要排最多件,還是排最重要的事情?」這其實就是在選模型。
| 情境 | 較適合的方法 | 理由 |
|---|---|---|
| 你想在一天內塞進最多個短任務 | 貪婪區間排程 | 目標是最大化可安排數量,規則簡單、速度快,也容易解釋 |
| 任務的重要性差很多,例如高價值客戶拜訪比內部例會更重要 | 加權排程 | 目標改成最大化總效益,而不是單純多排幾件 |
| 你需要先快速估一版可行清單,再和同事協調 | 先做貪婪排程,再看衝突清單 | 先用簡單規則拿到初稿,比較容易在會議中討論 |
| 你要向主管說明為什麼某些時段被保留給少數任務 | 加權排程 | 可以清楚說明取捨依據是效益總和,而不是個人偏好 |
可以把它想成兩層問題:
先問自己目標是不是「排最多件」。
如果不是,再明確定義每件事的價值,改用加權排程。
這個差別很重要,因為貪婪排程很適合當成第一版決策工具,但只要任務價值差異開始擴大,模型就應該跟著升級,否則你可能會得到一份很滿的行程表,卻不是最值得執行的一天。
實作範例¶
請參考 examples/ch06/scheduling.py。請在專案根目錄執行程式,以確保路徑正確。
from examples.ch06.scheduling import select_non_overlapping_tasks, select_highest_value_tasks
tasks = [
{"name": "Team A Meeting", "start": 9, "end": 11, "value": 30},
{"name": "Client Call", "start": 10, "end": 12, "value": 50},
{"name": "Sync Up", "start": 11, "end": 13, "value": 20},
{"name": "Project Review", "start": 13, "end": 15, "value": 40},
]
# 1. 貪婪法:排最多件
most_tasks = select_non_overlapping_tasks(tasks)
print("最多件安排:", [t["name"] for t in most_tasks])
# 最多件安排: ['Team A Meeting', 'Sync Up', 'Project Review']
# 2. 加權排程:總效益最高
best_value, best_tasks = select_highest_value_tasks(tasks)
print(f"最高效益 ({best_value}):", [t["name"] for t in best_tasks])
# 最高效益 (90): ['Client Call', 'Project Review']示範流程包含:
依結束時間排序任務
貪婪地挑出互不重疊的可行清單
用動態規劃找出總效益最高的任務組合
把首尾相接的時段視為可相容
另外列出彼此衝突的任務配對