最近在做大促需求的時候,根據與產品討論出來的乙個優化方案涉及到兩個個人感覺很不錯的演算法知識,可以簡單的抽象成資料結構演算法問題。特此分享一下此次實戰中的一些思路。
前言:乙個揀貨任務是倉庫內分配作業人員的最小單位,即乙個作業人員通過手持rf裝置即可獲取乙個揀貨任務,這個揀貨任務包含多個商品,也就是乙個揀貨單包括多個揀貨明細。這個明細主要包含資訊為庫位,需要揀的數量,商品名稱。
概念介紹:
揀貨任務
動線排序
乙個作業人員獲取乙個任務,然後根據這個揀貨任務的明細進行乙個乙個揀貨,完成揀貨任務,如何達到最佳的揀貨路線,我們會根據根據路線進行乙個排序,庫位是有編號的,這個編號可以簡單理解成是物理順序排列的,我們系統生成的時候也要根據這個順序排好序這樣可以讓作業人員順序走動,避免來回走動。
揀貨容器
其實這次要解決的乙個問題是乙個容器裝箱問題,作業人員會拿乙個容器去進行揀貨,系統現狀是乙個揀貨任務就拿乙個容器,這樣存在乙個問題,乙個揀貨單或許裝不滿,這次就是要提公升裝載率。
考慮到改動成本,我們把揀貨單控制成乙個揀貨單只包含乙個明細,這樣其實就是乙個揀貨單乙個貨位乙個商品的維度了,然後根據每個揀貨單的體積(即每個庫位商品要揀的體積)來計算需要的容器是否裝滿。最後根據條件,把盡量連續裝滿的揀貨單合併在乙個分組裡。(這樣能夠一起揀貨裝在乙個容器)
抽象成這樣乙個問題,連續的庫位的揀貨單,如果體積合在一起就成乙個組,超過為單獨乙個組。
假設體積為100~110都算裝滿,這樣的乙個排序。哪些能組成乙個分組呢。
根據演算法:
首先看20,不夠加入乙個虛擬的暫存區
到70加暫存區合計90仍然不滿
30合計暫存區超過110,丟棄暫存區頭。注意這裡為什麼不是整個丟棄暫存區,就是如果是那樣,就會丟失70+30這次組包成功,這是符合預期的值。
不難得出最後能組成一組的值是:70+30+40.
這裡存在另乙個概念,是否甩尾,所謂的尾巴就是容器內空閒的體積,甩尾即是裝滿的意思,不甩尾就是不裝滿。我們的演算法設計是支援是否甩尾的。所以如果保證組出來的一定是裝滿的,就只能得出上面一組結果,剩餘的揀貨任務,在一定時間內無法裝滿也需要強制走掉,就是允許不甩尾去揀貨,這樣上面同樣的條件就可以組成。當然,並不是不滿就一組,應該盡量讓其裝滿,其思路為:
20不夠,放入暫存區
70+暫存區20合計90,不滿
90+30超過容器,90組成乙個分組,30加入暫存區
…合計出來的結果分組為 20+70 30+40+40 80
talk is cheap , show the code
private list> combinecontainerbyvolume(long warehouseid, listtasklist, containertypedto containertypedto, boolean iswithouttail) else
}continue;
}/**
* 合計暫存體積與當前揀貨單
*/double volume = currentpickunit.getvolume().doublevalue();
for (pickunitdto pickunitdto : tailpicktaskmodellist)
if (matchofcontainer(bigdecimal.valueof(volume), containertypedto))
tailpicktaskmodellist.clear();
picktaskmodellist.add(pickunitdtolist);
} else if (iscontainerover(bigdecimal.valueof(volume), containertypedto)) else }}
} else
}if (collectionutils.isnotempty(tailpicktaskmodellist)) }}
return picktaskmodellist;
}
演算法2
由於揀貨單的順序之間關係到作業人員的作業順序,因此根據動線排序完成後,會發現同庫位同商品早生成的揀貨單可能後作業,因此這裡就產生另乙個問題,在同樣庫位商品情況下進行區域性排序。
例如這樣的情況,需要對5-3-4進行排序。抽象為陣列的區域性排序:
private void extsortbygmt(listpicktaskdetailmodellist)
if (samecabinetidpointerpicktaskdetaillist.size() > 1) else if (o1.getid() > o2.getid())
return 0;
});sortedpicktaskdetaillist.addall(samecabinetidpointerpicktaskdetaillist);
} else
samecabinetidpointerpicktaskdetaillist.clear();
}picktaskdetailmodellist.clear();
picktaskdetailmodellist.addall(sortedpicktaskdetaillist);
}
總結
很多人覺得做業務需求基本就是curd,其實複雜的業務需求也會涉及很多演算法,程式=資料結構+演算法是很有道理的,只是我們平時用的複雜演算法很多已經被封裝成開源庫,這不是讓我們忘記演算法的重要性,而是讓我們可以更專注於業務。如果不重視,真的到遇到業務需求上的演算法難題就麻煩了。本文的提到的演算法,例如體積組合的那個問題,我相信還有更好的解決方案,例如如果可以跨分割槽組為乙個分組,那問題將變得異常複雜,這裡更涉及到動線與體積的優先順序問題,在兩者之間做個權衡並達到效率最高,這可能已經超過技術側重思考的問題,對於技術人員已經超綱。但是這可能也是作為技術人員反推業務去思考的點。
OTP在實際專案中的整合
提起動態令牌,大家都會想到認證伺服器,而這個認證伺服器又怎麼應用到實際的應用系統中呢?在這裡做乙個分析和說明,幫助廣大使用者能夠更好的使用otp動態令牌這種身份認證產品。從前面otp原理部分中可以看出,伺服器端是在乙個範圍內計算出多個otp,然後檢驗客戶端硬體產生的otp口令是否在這個範圍內。那麼伺...
元件在實際專案中的使用
元件在實際專案中的使用 自動封裝元件 封裝元件後元件間傳值 父傳子props 子傳父 emit 元件事件的呼叫 在父元件內 元件標籤新增ref 自定義名 this.refs.自定義元件名.子元件方法 元件插槽 套入資料或分開布局 slot的使用就像它的名字一樣,在元件內定義一塊空間,取名為slota...
關於cachedrowset在實際專案中的應用
由於專案需求原因,需要實現乙個功能就是,抽取大量的資料庫資料然後寫入文字並打包上傳。看似乙個很簡單的東西,在大資料量的環境下就顯得不是那麼簡單了。首先有60張左右的表需要進行資料的處理。各個公司情況不同,表的總資料量可能是幾千萬到幾十億不等。所以,耗時非常嚴重。由於只是單純的進行資料的提取加工寫入文...