ナップザックを最適に埋めるための動的計画法アルゴリズムは、1つのナップザックの場合にうまく機能します。しかし、2つのナップザックを最適に満たす効率的な既知のアルゴリズムはありますか(容量は等しくない可能性があります)?
私は次の2つのアプローチを試しましたが、どちらも正しくありません。
問題の説明(ウィキペディアの ナップサック問題 も参照):
総重量がナップザックのサイズ以下でありながら、アイテムから得られる価値を最大化するために、ナップザックにアイテムのセット(各アイテムには重量と値があります)を入れる必要があります。
アイテムを複数回使用することはできません。
n
の各アイテムは1回しか使用できないと想定し、利益を最大化する必要があります。
オリジナルのナップザックは_dp[i] = best profit you can obtain for weight i
_です
_for i = 1 to n do
for w = maxW down to a[i].weight do
if dp[w] < dp[w - a[i].weight] + a[i].gain
dp[w] = dp[w - a[i].weight] + a[i].gain
_
これで、2つのナップザックがあるので、_dp[i, j] = best profit you can obtain for weight i in knapsack 1 and j in knapsack 2
_を使用できます。
_for i = 1 to n do
for w1 = maxW1 down to a[i].weight do
for w2 = maxW2 down to a[i].weight do
dp[w1, w2] = max
{
dp[w1, w2], <- we already have the best choice for this pair
dp[w1 - a[i].weight, w2] + a[i].gain <- put in knapsack 1
dp[w1, w2 - a[i].weight] + a[i].gain <- put in knapsack 2
}
_
時間計算量はO(n * maxW1 * maxW2)
です。ここで、maxW
はナップザックが運ぶことができる最大重量です。容量が大きい場合、これはあまり効率的ではないことに注意してください。
元のDPは、dp配列で、ナップザックで取得できる値をマークすることを前提としています。更新は、結果として要素を考慮して行われます。
2つのナップザックの場合、2次元の動的配列を使用できるため、dp [i] [j] = 1重みを付けることができる場合i to最初と重量j 2番目のナップザックに。更新は元のDPの場合と同様です。
再帰式は誰もが探しているものです:
アイテムiが重みwiと値piを持つように、n個のアイテムが与えられます。 2つのナップザックはW1とW2の容量を持っています。
0 <= i <= n、0 <= a <= W1、0 <= b <= W2ごとに、M [i、a、b]の最大値を示します。
a <0またはb <0の場合-M [i、a、b] = −∞ i = 0の場合、またはa、b = 0-M [i、a、b] = 0
式:M [i、a、b] = max {M [i-1、a、b]、M [i-1、a-wi、b] + pi、M [i-1、a、b- wi] + pi}
Iアイテムの問題に対するすべての解決策には、アイテムiがナップザック1にあるか、ナップザック2にあるか、いずれにもありません。