理解を深めるために、類似の例を取り上げるシナリオがあります。
既知のさまざまな容量のN個のバケットがあります。 M
個のボールがあり、これらのバケットを完全にまたは部分的に満たすために入れる必要があります。既存のアルゴリズムは次のように機能します。
各バケットについて、割合effect = (Bi + 1)/Ci
を計算します。ここで、Bi
とCi
は、バケット内の現在のボール数とith
バケットの容量です。効果が最も低いバケットを特定し、Mからボールを入れます。ボールがなくなるまで(_M=0
_)、またはすべてのバケットが定員に達するまで、上記のプロセスを繰り返します。
上記のアルゴリズムは目的の出力を生成しますが、割り当てるバケットとボールの数が多い場合はパフォーマンスの問題が発生します。すべてのボールを割り当てるには、内側のループで_M * N
_を実行する必要があります。
各バケツにボールをまとめて割り当てて最適化してみました。新しいアプローチは次のとおりです。
バケットごとに、次のようにします。差(全容量に満たないボールの数)_Di = Ci - Bi
_を計算します。いいえを計算します。バケットに入れるボールの数Mi = (Di * M)/S
ここで、Sはすべてのバケットの差(D1 + D2 .... Dn)の合計です。
ただし、はるかに高速ですが、特にすべてのバケットを満たすのに十分なボールがない場合、結果は前のアプローチと同じではありません(つまり、M <S)
M
にほとんど依存せず、一度に1つのボールを割り当てる元のアプローチと同じ出力を生成するアルゴリズムを誰かが提案できますか?
ボールをバケツに入れたときにのみ再計算することで最適化できます。つまり、M * Nの代わりにM + Nの計算が行われます。
もちろん、これは計算を保存するためにメモリが必要であることを意味します。バケットごとに1つ。
また、優先度キューに保持することで、最も効果の低いバケットの検索を最適化することもできます。