動態規劃之揹包問題--python版本

動態規劃之揹包問題–python版本

問題

已知一個最大量的揹包,給定一組給定固定價值和固定體積的物品,求在不超過最大值的前提下,能放入揹包中的最大總價值。

解題思路

該問題是典型的動態規劃問題,分爲三種不同的類型(0-1揹包問題、完全揹包和多重揹包問題)

解題關鍵–狀態轉移表達式:
B(k,C)=max(B(k1,C),B(k1,Cci)+vi) B(k,C) = max(B(k-1,C), B(k-1,C-c_i)+v_i)

  • k表示總共物品爲k件
  • C表示揹包總容量
  • cic_i表示第i件物品佔用容量
  • viv_i表示第i件物品價值

0-1揹包

from _ctypes import Array


class Knapsack:
    c: Array = [0, 2, 5, 4, 3, 6]  # capacity 各個物品容量
    v: Array = [0, 3, 4, 6, 7, 6]  # value權值
    f: Array = [0 for i in range(0, 21)]  # 存放結果 需要初始化,否則數組會越界

    def bag_1(self, capacitySum):
        '''
        通俗算法
        時間複雜度:O(capacitySum * n)
        空間複雜度:O(capacitySum * n)
        :param capacitySum: 包的總容量
        :return: 返回求解的數組的
        '''
        n = len(self.c)

        res = [[0 for col in range(21)] for row in range(n)]
        for i in range(1, n):
            for j in range(1, capacitySum + 1):
                if self.c[i] > j:
                    res[i][j] = res[i - 1][j]
                else:
                    # 當前狀態爲 前一個狀態最優解 與 選取第i件商品的價值和剩餘空間最優解 的最大值
                    res[i][j] = max(res[i - 1][j], res[i - 1][j-self.c[i]] + self.v[i])
        return res

    def bag(self, capacitySum):
        '''
        優化空間算法
        時間複雜度:O(capacitySum * n)
        空間複雜度:O(capacitySum * 1)
        :param capacitySum: 包的總容量
        :return: 返回求解的數組的
        '''
        n = len(self.c)
        for i in range(1, n):
            # 此處爲倒敘,正序在計算過程中不能表示上一個狀態的值,被更新啦
            for j in range(capacitySum, self.c[i] - 1, -1):
                self.f[j] = max(self.f[j], self.f[j - self.c[i]] + self.v[i])
        return self.f

完全揹包

完全揹包問題是指每種物品都有無限件

from _ctypes import Array


class Knapsack:
    c: Array = [0, 2, 5, 4, 3, 6]  # capacity 各個物品容量
    v: Array = [0, 3, 4, 6, 7, 6]  # value權值
    f: Array = [0 for i in range(0, 21)]  # 存放結果 需要初始化,否則數組會越界

    def bag_complete(self, capacitySum):
        '''
        優化空間算法
        時間複雜度:O(capacitySum * n)
        空間複雜度:O(capacitySum * 1)
        :param capacitySum: 包的總容量
        :return: 返回求解的數組的
        '''
        n = len(self.c)
        for i in range(1, n):
            # 此處爲正序,完全揹包需要是當前揹包的最優解,必須從頭開始
            # 從c[i]開始,因爲i前面的最優解,直接照抄 而同一個數組不需要變化
            for j in range(self.c[i], capacitySum + 1):
                self.f[j] = max(self.f[j], self.f[j - self.c[i]] + self.v[i])
        return self.f

多重揹包問題

多重揹包問題限定了一種物品的個數,解決多重揹包問題,只需要把它轉化爲0-1揹包問題即可。比如,有2件價值爲5,重量爲2的同一物品,我們就可以分爲物品a和物品b,a和b的價值都爲5,重量都爲2,但我們把它們視作不同的物品。

參考

揹包問題:0-1揹包、完全揹包和多重揹包

[Algorithm][011] 動態規劃 Dynamic Programming(DP) 揹包DP 3講 [OTTFF]

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章