tsp目錄算法
- 最簡單的實踐 juejin.im/post/5d1b14…
- 最簡單的理論 juejin.im/post/5d1b15…
- 當前tsp的現狀 juejin.im/post/5d1b19…
- 單起點任務分配 juejin.im/post/5d1c6d…
- 多起點任務分配 juejin.im/post/5d1dbe…
- 更簡潔的多起點分配 juejin.im/post/5d1dc2…
- 起點時間窗 juejin.im/post/5d1f1f…
- 終點時間窗和hk juejin.im/post/5d1f44…
- LK簡介 juejin.im/post/5d25b8…
- tsp系列暫停一下 juejin.im/post/5d302e…
tsp領域的問題, 並不都是tsp問題, 可是, tsp相關的算法通常都能解決, 只要你能爲某一個充滿個性的問題兒子找到他親生的解決方案爸爸.數據結構
問題概述
- 做爲一家新興微(蟹)商, 你有一個倉庫/發貨點, 天天要進行全城配送, 你面臨的問題和傳統快遞業終端網點面臨的幾乎同樣的問題,
- 區別在於, 傳統網點容量有限, 人肉分配是常態, 而且實際上人肉分配是最高效的方案. 可是, 你的微(蟹)商發貨, 天天要達到>300單, 若是人肉分配, 那麼須要一組人, 大半夜的就開幹, 還很容易出現各類問題.
- 有傳統的圍欄是一個解決方案, 可是, 他的成本不是最優的, 會致使你在微(蟹)商的競爭中處於劣勢.
- 再考慮一種狀況, 你是一個在集散地作配送的物流公司, 如何合理的調度車輛, 成爲你最核心的競爭力.
建模和思考
面臨這樣一個問題, 粗略一看就是tsp問題, 你只要保證分配好的全部配送員的總路線最短就能夠了. 可是, 實際上, 咱們能夠簡化問題. 這裏咱們要引入一個前提和一個猜測.post
- 前提: tps問題能夠和最小生成樹對應起來, 對於最小生成樹的遍歷, 就自動造成一條路徑, 並且這條路徑能夠保證<2倍的最短路徑. 由於最小生成樹的深度遍歷致使走了兩遍. 而最小生成樹自己的總長度確定小於最短路徑. 以下圖示意.
- 猜測: 那麼咱們能夠認爲, 一組點, 他們的最小生成樹比較小, 那麼他們的路徑在很大的機率上也會比較短.
方案: 咱們可使用最小生成樹作訂單分配
由於, 最小生成樹有好幾個多項式時間的算法, 所以, 咱們此次不只僅解決了300單的分配問題, 3000單, 30000單, 都沒有問題了. 只要知足單一塊兒點(倉庫/發貨點)這個條件.測試
最小生成樹的主力算法有兩個:優化
咱們逐一介紹一下:設計
克魯斯卡爾3d
- 從一個點集中找到最短的路線, 加到樹裏面,
- 而後剩下的裏面繼續找最短的, 若是能連在一塊兒就連在一塊兒, 不然就保持森林狀態,
- 直到某一個線段加進來以後, 森林裏面的最後兩棵樹也連在一塊兒造成一棵大樹, 那麼算法中止.
普利姆cdn
- 從一個點集中任意找一段路線, 加到樹裏面
- 而後, 此時樹裏面有2個點, 那麼查找距離這兩個點最近的點, 把他加到樹裏面.
- 此時樹裏面有3個點, 再加入離這三個點最近的點.
- 直到全部點都加入, 算法終止.
從描述咱們能夠看出來, 克魯斯卡爾的開銷要大一些, 由於他要作全部距離的排序, 而普利姆每次都是一個不大的範圍裏面找最近的一個值. 不過克魯斯卡爾其實有很大的優化空間, 這裏要引入一個概念: 鄰域.blog
- 鄰域: 一個點相鄰的一個或者多個點組成的一組點就是一個鄰域.
- 克魯斯卡爾能夠只保留每一個點最近的3-5個距離進行排序, 最終組成樹, 不過這樣可能造成森林, 可是, 不要緊, 最後再補充須要的幾個距離就能夠了. 這個思路很是有用, 將來的線性規劃方案就用到了這個思路.
此次的算法設計是一次正常的設計: 數據結構引領算法
總體算法的思路是:排序
- 從起點開始, 用普利姆構造一棵樹.
- 在對這個樹的遍歷過程當中, 按照每一個司機的工做量, 拆分這棵樹爲一段一段的子樹.
- 樹分完爲止, 或者司機耗盡.
後記:
- 這個分配是很是快速的, 實際測試中能夠發現即使在普通的開發機上, 也能夠秒分1萬單.
- 貌似咱們隨手就解決了一個很大的問題, 別急夥伴們, 現實問題永遠比數學問題複雜, 咱們的系列講解纔剛剛開始.
- 這個算法最大的感觸就是: 沒有廢的算法, 只有對的算法, 好比咱們能夠用不少精確算法來作這件事, 可是不必, 並且, 路徑算法直接映射到咱們這個分配問題上, 還有很大的困難, 咱們須要對問題作轉化才行.
這篇分享一鼓作氣, 總共只花了半小時, 由於它起源於個人實際項目, 在複雜的現實問題中, 敏銳的把握了核心業務, 我都佩服本身了. 轉載請附上本文連接, 首發掘金.