Cプログラミング
 Computer >> コンピューター >  >> プログラミング >> Cプログラミング

C/C++で分枝限定法(Branch and Bound)を用いて0/1ナップサック問題を解く方法

0/1ナップサック問題と分枝限定法

0/1ナップサック問題では、各アイテムを「ナップサックに入れる」か「入れない」かの二者択一で選ばなければなりません。この組み合わせ最適化問題を効率的に解く手法の一つが分枝限定法(Branch and Bound)です。

このアルゴリズムの鍵となるのは、「分数(Fractional)ナップサック問題、つまりアイテムを分割して入れられる問題に対しては、貪欲法が最適解を与える」という性質を活用する点です。探索の過程で生じる各ノードについて、この貪欲法を応用して上限値(バウンド)を求めることで、無駄な探索を切り捨てることができます。

ある特定のノードからより良い解が得られる可能性があるかどうかを調べるには、そのノードを経由した場合の最適解(上限値)を貪欲法で計算します。もし貪欲法によって得られた解が現時点での最良解(best so far)以下であれば、そのノードを深掘りしても改善は見込めないため、そこで探索を打ち切る(枝刈りを行う)ことができます。

アルゴリズムの全体像

完全なアルゴリズムの手順は以下の通りです。

  1. アイテムのソート:単位重量あたりの価値(価値÷重みの比率)が高い順にすべてのアイテムを並べ替えます。これにより、貪欲法を用いて上限値を計算できるようになります。

  2. 初期化:最大利益を格納する変数を maxProfit = 0 として初期化します。

  3. キューの作成:空のキュー Q を生成します。

  4. ダミーノードの追加:決定木のルートとなるダミーノードを作成し、キュー Q に挿入(エンキュー)します。ダミーノードの利益と重みはともに 0 です。

  5. 探索の繰り返し:キュー Q が空になるまで、以下の処理を繰り返します。

    • キュー Q からノードを1つ取り出します。取り出したノードを u とします。

    • 次のレベルのノードについて、そのアイテムを解に含めた場合の利益を計算します。この利益が maxProfit より大きければ、maxProfit を更新します。

    • 次のレベルのノードについて、上限値(バウンド)を計算します。この上限値が maxProfit より大きい場合は、まだ改善の余地があるため、そのノードをキュー Q に追加します。

    • さらに、次のレベルのアイテムを解に含めないケースも考慮します。この場合は、レベルだけを1つ進めたノード(次のアイテムの重みと利益を加えないノード)をキューに追加します。

実行例

具体的な入力と出力の例を以下に示します。

入力

// 各ペアの最初の値はアイテムの重み
// 2番目の値はアイテムの価値を表す
Item arr1[] = {{2, 40}, {3.14, 50}, {1.98, 100}, {5, 95}, {3, 30}};
Knapsack Capacity W1 = 10

出力

The maximum possible profit = 235

この例では、重み2・価値40、重み1.98・価値100、重み5・価値95の3つのアイテムを選ぶことで、総重み8.98(容量10以内)となり、最大利益235が達成されます。分枝限定法を使うことで、全数探索を避けながら効率的にこの最適解へたどり着けるのです。

  1. C++で調和級数 1 + 1/2 + 1/3 + 1/4 + … + 1/n の合計を求めるプログラム

    この問題では、数値 n が与えられます。私たちのタスクは、C++で級数 1 + 1/2 + 1/3 + 1/4 + … + 1/n の合計を求めるプログラムを作成することです。コードの説明ここでは、級数 1 + 1/2 + 1/3 + 1/4 + … + 1/n の第 n 項までの合計を求めます。この級数は「調和級数」と呼ばれるものです。調和数列(Harmonic Progression)とは、各項の逆数を並べると等差数列になる性質を持つ数列のことです。つまり、調和数列 A1, A2, A3, …, An に対して、その逆数である 1/A1, 1/A2, 1/A3, … が等差数列を構成します

  2. C++で0/1ナップサック問題を解き、選ばれたアイテムを出力する方法

    n個のアイテムの重さと価値が与えられたとき、容量Wのナップサックに収まる範囲で合計価値が最大になるようにアイテムを選び、実際に選ばれたアイテム(重さ)を出力するのが本記事の目的です。 0/1ナップサックとは? ナップサックとは、サイズや耐えられる重量が固定された袋のことです。ナップサックに入れる各アイテムには、それぞれ価値(利益)と重さがあります。ナップサックが保持できる総重量の範囲内で、利益が最大になるようにアイテムを選ぶ必要があります。 各アイテムの重さ、価値(利益)、そしてナップサックが保持できる総重量が分かっているとき、0/1ナップサックでは各アイテムを「入れる(1)」か「入れない(0