--0,1ナップザック問題をプログラミングダイナミック(もはや恐れる同様のナップザック問題の)

この種の問題三つの要素:総重量、各項目の重み、各項目の値は、最終的にバックパックの最大値に詰め掲載してどのくらいですか?どのように項目を選ぶべきなのでしょうか?

総数は、座席掘る鉱山あたりの人々の数、座席あたりの金鉱石の数:もちろん、必ずしもそれらの、例えば、セクションでは、採掘鉱山労働者を言いました。

換言すれば、限り、これらの三つの要素があったとして、それは0,1ナップザック問題(項目分けされていない)と見なすことができます

国境、最適なサブ構造、状態遷移方程式:ダイナミックは、3つの要素をプログラミングします。

私たちは、ステップ解析によるステップがあります。

初期化:項目総重量:C = 8。 商品カテゴリ:N- = [ 'A'、 'B'、 'C'、 'D'] アイテムの重量:W = [2,4,5,3] 商品の価値:V = [5,4,6,2]

私たちは、1つの項目aがあることを前提とし、

  • バックパックの総重量は、私たちが0の合計値を取得するには、0であります
  • バックパックの総重量は、我々は1の合計値を取得し、1であります
  • バックパックの総重量は、ちょうどその重量はわずか2であるので、我々は5の合計値を取得する項目を下に置くために、この時点では、2であります
  • その後、我々は、合計値が5で取得することができます2>の総重量、一つだけのアイテム理由

私たちは今、もう一つのアイテムBがあるとし、

  • バックパックの0総重量は、次に我々は、0の合計値を取得します
  • バックパック1の総重量は、次に我々は、0の合計値を取得します
  • バックパック2の総重量は、その後、あなたが置くことができ、我々は5の合計値を取得します
  • バックパック3の総重量は、まだだけ入れて、我々は5の合計値を取得します
  • 4バックパックの総重量、そして私たちはどちらかに置くことができ、Bを置くことができ、に、最大値を、選択し、その後、我々は5の合計値を取得します
  • バックパックの5総重量は、我々は5の合計値を取得します
  • 6バックパックの総重量は、その後、あなたが置くことができ、B、そして我々は、の合計値を求める5 + 4 = 9
  • その後、我々は両方の合計値を得ることができます9

私たちは今、複数の項目cを想定し

  • バックパックの0総重量は、次に我々は、0の合計値を取得します
  • バックパック1の総重量は、次に我々は、0の合計値を取得します
  • バックパック2の総重量は、その後、あなたが置くことができ、我々は5の合計値を取得します
  • バックパック3の総重量は、まだだけ入れて、我々は5の合計値を取得します
  • 4バックパックの総重量、そして私たちはどちらかに置くことができ、Bを置くことができ、に、最大値を、選択し、その後、我々は5の合計値を取得します
  • バックパックの5総重量、我々は置くことができ、その後、あなたはまた、Cを置くことができ、その後、我々は6の合計値を取得し、Cの中に、あること、最大を選択
  • 6バックパックの総重量は、今回は、Bに入れることができ、及びCは、最大が選択され、我々は> 6 4 + 5 = 9の合計値を求め、置くことができます
  • その後、我々は両方の合計値を得ることができます9

そして、その下に、かなり実際には、私たちが達成すべき、その後どのように、ルーチンがあり、複雑に見えます。

この問題に対処し、一般的に直接配列を初期化:DP [lenは(N)+1] [C + 1]、すなわち、5行(行の二次元アレイは、より賃金の、列が総重量を表し、オブジェクトの種類を表し、9それが簡単に理解できるようにするライン)

次に、我々は、コードのステップ解析によって一歩を踏み出します。

n=['a','b','b','d']
c=8
w=[2,4,5,3]
v=[5,4,6,2]
def bag(c,w,v):
    #初始化数组,dp[i][j]表示总重量为j,物品种类为i,可以获得的最大价值
    dp = [[0 for _ in range(c+1)] for _ in range(len(w)+1)]
    #定义边界,也就是当我们只有物品a,总重量依次由0-8
    #也就是第一步我们所解释的
    for i in range(1,c+1):
        if i>=w[0]:
            dp[1][i] = v[0]
    #遍历从第二行第一列开始
    for i in range(2,len(w)+1):
        for j in range(1,c+1):
            #如果对于第i个物品,当前总重量放不下它,那么获得的最大值就是放下之前的i-1个
            if j<w[i-1]:
                dp[i][j] = dp[i-1][j]
            #如果放得下,那么获得的最大值就是max(放下之前的i-1个,第i个物品的价值+
            # (总重量-第i个物品的重量)在前i-1个物品的值)
            #注意下标,第i个物品的重量是w[i-1],价值是v[i-1]
            else:
                dp[i][j]=max(dp[i-1][j],dp[i-1][j-w[i-1]]+v[i-1])
    return dp
def show(c,w,dp):
    print("最大价值为:",dp[len(w)][c])
    x = [False for _ in range(len(w)+1)]
    j = c #8
    i = len(w) #4
    while i>=0:
        if dp[i][j]>dp[i-1][j]:
            x[i]=True
            j=j-w[i-1]
        i-=1
    print("选择的物品是:")
    for i in range(len(w)+1):
        if x[i]:
            print("",i,"",end='')
    print('')
dp = bag(c,w,v)
for i in range(len(w)+1):
    print(dp[i])
show(c,w,dp)

运行结果:

 

最后在输出第几个物品的时候采用由下往上,如果下面的值大于上面的值,说明这个物品被放置了,然后总重量减去该物品重量,继续判断,如蓝色所标记的。

总结:背包问题三步走:

(1)初始化dp数组,行为物品个数+1,列为总重量+1

(2)初始化边界,只放一个物品,在不同总重量下得到的价值

(3)遍历数组,依赖dp[i-1]更新dp[i]

おすすめ

転載: www.cnblogs.com/xiximayou/p/12004082.html