假設所有的百分比給定的陣列中是小於100(在任何情況下,如果有在元件或大於100,我們可以計算,並立即將其刪除),100%的各筒不能從少於兩個被創建陣列元件,和100個%的桶數不能超過該陣列的由100。因此,準備檢查劃分的總和被約束:
maxNumBarrels array = min (div (sum array) 100) (div (length array) 2)
以下Haskell代碼提供的功能,divide
,它將數組分割成n個分區的所有變體而不重複(即忽略分區內的分區順序和元素順序)。函數maxBarrels
向後搜索,首先將數組劃分爲maxNumBarrels分區(使用總和大於等於100的maxNumBarrels元素搜索結果),然後逐漸減少數量的分區,直到找到答案或返回空集。
import Data.Map (adjust, fromList, toList)
divide xs n = divide' xs (zip [0..] (replicate n [])) where
divide' [] result = [result]
divide' (x:xs) result = do
index <- indexes
divide' xs (toList $ adjust (x :) index (fromList result)) where
populated = map fst . filter (not . null . snd) $ result
indexes = populated ++ if any (null . snd) result
then [length populated]
else []
maxBarrels xs = allDivided maxNumBarrels where
maxNumBarrels = min (div (sum xs) 100) (div (length xs) 2)
allDivided count | count == 0 = []
| not (null divided) = divided
| otherwise = allDivided (count - 1)
where divided = filter ((==count) . length)
. map (filter ((>=100) . sum))
. map (map snd)
. divide xs $ count
OUTPUT:
*Main> maxBarrels [10,15,20,35,55,65]
[[[55,20,15,10],[65,35]],[[55,35,10],[65,20,15]]]
*Main> maxBarrels [99,99,99]
[[[99,99,99]]]
*Main> maxBarrels [99,99,99,10,15,25,35,55,65]
[[[15,10,99],[25,99],[35,99],[65,55]] ...(the first of 144 immediate results)...
這似乎是裝箱的變化,這是NP難,但有很多很好的近似方案。你需要找到最佳答案還是可以近似它? – Paulpro 2013-04-27 20:46:57
Paulpro提到的用於裝箱的鏈接http://en.wikipedia.org/wiki/Bin_packing_problem。它的推薦閱讀讓你瞭解和選擇你選擇的方法來解決問題。 – Zeddy 2013-04-27 23:32:51
@Paulpro變體?這看起來像一個確切的BPP給我。 – 2013-04-28 17:15:11