[ダイナミックプログラミング]ナップザック問題

問題の説明

01ナップザック問題は:Nの項目がありますが、各項目は、プロパティの2つのボリュームと価値を持って、固定容量のバックパックは、今そこにある、あなたはバックパックの中にこれらの項目をしたい、バックパックで最大の項目の合計値を作成し、配置する方法を尋ねましたか?

注:各項目の数は1です。

集合$ V = 14 $。

説明の便宜のために、我々は、$ C_1、C_2、C_3を使用し、... C_N $は$ W_1、W_2、w_3と、品物の体積であり、.... W_N $は$ V $エクスプレスバックパックと、商品の値を表します容量、$ N $は、アイテムの数です。

動的計画説明

ナップザック問題は分割統治法、それは問題に少し大きな問題であるとして、次に、大小の問題との間の再帰的な問題を見つけ、動的プログラミング問題であり、そして、小さな問題に結合します大きな問題、

そして、通常、これらの必要が小さな問題が最適持っています:動的なプログラミングの問題は、一般的に2つのプロパティを含んで解決することができ、最適な下部構造体の重複部分の問題を。本質的に動的計画法は網羅され、それはアルゴリズムの一般的な効率が高くなるよりも、

それは全体的な複雑性はそれほど高くない作り、重複部分問題を切ることができるからです。

 

ソリューション

1.再帰的な方法

のは、この問題を解決するための再帰的な方法で開始することで開始する最も簡単なところから始めましょう。

リリースまたは保留:まず、各項目ごとに、我々は2つの選択肢があります。我々は、すべてのおそらく疲労のうちの、次のツリー図を(最初の4つのノードを描いた)を取得することができます。

このツリーは、各ブランチは一つだけを選ぶことができ、各ラインは、サブ問題を表しています。私たちは(私は、V_I)$バックパックにアイテムで前に$ I $番目の最大値を表す(つまり、最適解である)$ Fを使用して、私はバックパックのアイテムを$ $配置する前に、この$ v_iを$ポストを指し、残りの容量。

明白$ F(5、v_5)$は、問題が突然、スプリットのすべてということです、私たちが解決しなければならない大きな問題です:$ F(1、V_1) $、$ F(2、V_2)$、$ F(3、v_3)$、 $ F(4、v_4)$ 。この大きな問題を解決するために、我々は最初の$ Fの前にその問題の子を解決しなければならない(4、v_4)$ ( 、元の問題だけでなく、次善の問題を解決する問題が持つように、最適な下部判断され、動的プログラミング溶液の条件の1つ)を通報することができます。

$ F解決する理由については(5、v_5)最初の前に(、4 v_4)$の$の問題を$ Fを解決しなければならない$ F(4、の問題を解決している場合、この理由は、$ $ F(v_5 5)のための問題であり、 V_4)$レストのみ物品は、バックパックの残量量より大きいかどうかを最終的な決意を必要とする、バックパックは、直接に、または保持することです。

$サブ問題$ F(v_4 4)については、我々は$ F解決しなければならない(3、v_3)$ ...こうして$ F(1、V_1)$に対処しなければなりません。それが唯一の裁判官の$ C_1を解決する必要があるので、何の問題の子は、その前に存在しないため、サブ質問の$ F(1、V_1)$の場合は\ルV $が成り立ちます。

リリース、またはホールド:サブ問題のフロントが解決されているので、だから、各サブ問題のために、私たちは2つのだけの選択肢を行う必要があります。

我々はすでに$(V、I-1)バックパック最適解$ Fに$ I-1 $の項目の前に知っていると仮定し、その後、$ I $バックパックに配置された最初の項目のための3つのケースがあります。

   記事のボリュームが$ V $の$ $ C_Iバックパックの残り容量よりも大きい場合、それは記事を破棄することができます。

     $ F(I、V_I)= F(I-1、V_I-1)$

   それ以外の場合は、2つのオプションがあります。

   1. $ Iは、物品のホールドを$:

    $ F(I、V_I)= F(I-1、V_I-1)$

   2.最初の$ iは番目の項目を$:

    $ F(I、V_I)= w_i + F(I-1、V_I -1- C_I)$

そう、これらの2つのシナリオの最大合計値を選択するには:

$$
F(i, v_i) =
\begin{cases}
F(i-1, v_{i-1}), & \text{ $c_i > v_{i-1}$ } \\
max(F(i-1, v_{i-1}), w_i +F(i-1, v_{i-1}-c_i)), & \text{ $c_i \le v_{i-1}$ }
\end{cases}
$$

 用Python实现代码如下:

#递归求解
def rec_bag(c, w, v, i):
    '''
    param c: 物品体积
    param w: 物品价值
    param v: 当前背包剩余容量
    param i: 当前物品编号
    return: 背包装下物品的最大价值
    '''
    if i > len(c)-1:
        return 0
    elif v <= 0: #体积不能为负
        return 0
    elif v > 0:
        if c[i] <= v:
            A = w[i] + rec_bag(c, w, v-c[i], i+1)
            B = rec_bag(c, w, v, i+1)
            res = max(A, B)#两种方案中选最优的那个并返回
        else:
            res = rec_bag(c, w, v, i+1)#物品体积大于背包容量,直接返回
    return res

代码我没有测试过,如果有错误可以在评论区告诉我。

后面动态规划解法和另外两个问题有时间再补充。

 

おすすめ

転載: www.cnblogs.com/Alevals/p/11600947.html