web-dev-qa-db-ja.com

2つのナップザックを埋める最適な方法は?

ナップザックを最適に埋めるための動的計画法アルゴリズムは、1つのナップザックの場合にうまく機能します。しかし、2つのナップザックを最適に満たす効率的な既知のアルゴリズムはありますか(容量は等しくない可能性があります)?

私は次の2つのアプローチを試しましたが、どちらも正しくありません。

  1. 最初に元のDPアルゴリズムを使用して最初のナップザックを埋めて1つのナップザックを埋め、次にもう1つのナップザックを埋めます。
  2. 最初にサイズW1 + W2のナップザックを満たし、次にソリューションを2つのソリューションに分割します(W1とW2は2つのナップザックの容量です)。

問題の説明(ウィキペディアの ナップサック問題 も参照):

  1. 総重量がナップザックのサイズ以下でありながら、アイテムから得られる価値を最大化するために、ナップザックにアイテムのセット(各アイテムには重量と値があります)を入れる必要があります。

  2. アイテムを複数回使用することはできません。

  3. アイテムの一部は使用できません。アイテムの一部を取ることはできません。 (すべてのアイテムは完全に含まれているかどうかのいずれかである必要があります)。
17
Nikunj Banka

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はナップザックが運ぶことができる最大重量です。容量が大きい場合、これはあまり効率的ではないことに注意してください。

11
IVlad

元のDPは、dp配列で、ナップザックで取得できる値をマークすることを前提としています。更新は、結果として要素を考慮して行われます。
2つのナップザックの場合、2次元の動的配列を使用できるため、dp [i] [j] = 1重みを付けることができる場合i to最初と重量j 2番目のナップザックに。更新は元のDPの場合と同様です。

1

再帰式は誰もが探しているものです:

アイテム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にあるか、いずれにもありません。

1
sheldonzy