揹包問題概述(Lintcode- 562.Backpack IV問題解決)

什麼是揹包問題

揹包問題(Knapsack problem)是一種組合優化NP徹底問題。問題能夠描述爲:給定一組物品,每種物品都有本身的重量和價格,在限定的總重量內,咱們如何選擇,才能使得物品的總價格最高。問題的名稱來源於如何選擇最合適的物品放置於給定揹包中。java

揹包問題是動態規劃算法的一個典型實例。動態規劃是對解最優化問題的一種途徑。它每每是針對一種最優化問題,根據問題的不一樣性質,肯定不一樣的設計方法。詳細能夠查到往期文章進行回顧,這裏主要圍繞Lintcode 平臺中的一個算法編程問題展開講解。算法

揹包問題的類型

揹包問題分爲0/1揹包,多重揹包、徹底揹包這三大類:編程

0/1揹包問題描述:給定n種物品和一揹包。物品i的重量是wi,其價值爲vi,揹包的容量爲C。問應如何選擇裝入揹包的物品,使得裝入揹包中物品的總價值最大?後端

對於一種物品,要麼裝入揹包,要麼不裝。因此對於一種物品的裝入狀態能夠取0和1.咱們設物品i的裝入狀態爲xi,xi∈ (0,1),此問題稱爲0/1揹包問題。數組

例子:01揹包問題描述:有編號分別爲a,b,c,d,e的五件物品,它們的重量分別是2,2,6,5,4,它們的價值分別是6,3,5,4,6,每件物品數量只有一個,如今給你個承重爲10的揹包,如何讓揹包裏裝入的物品具備最大的價值總和?優化

徹底揹包問題描述:有N種物品和一個容量爲V的揹包,每種物品都有無限件可用。第i種物品的體積是c,價值是w。求解將哪些物品裝入揹包可以使這些物品的體積總和不超過揹包容量,且價值總和最大?spa

例子:有編號分別爲a,b,c,d的四件物品,它們的重量分別是2,3,4,7,它們的價值分別是1,3,5,9,每件物品數量無限個,如今給你個承重爲10的揹包,如何讓揹包裏裝入的物品具備最大的價值總和?.net

徹底揹包問題與01揹包問題的區別在於每一件物品的數量都有無限個,而01揹包每件物品數量只有一個。設計

多重揹包問題描述:給定N種物品和一個容量爲C的揹包,第i種物品最多有 Mi件可用,每件的重量是Wi,價值是Vi。問:將哪些物品裝入揹包可以使這些物品的重量總和不超過揹包容量,且價值總和最大?code

例子:多重揹包問題描述:有編號分別爲a,b,c的三件物品,它們的重量分別是1,2,2,它們的價值分別是6,10,20,他們的數目分別是10,5,2,如今給你個承重爲 8 的揹包,如何讓揹包裏裝入的物品具備最大的價值總和?

多重揹包和01揹包、徹底揹包的區別:多重揹包中每一個物品的個數都是給定的,可能不是一個,絕對不是無限個。

下面簡單分析徹底揹包的狀況。

例子

給定一些物品數組和一個目標值,問有多少種能夠組成目標的組合數,好比給定物品數組 [2,3,6,7] 和目標值 7, 那麼就有2種可能:[7] 和 [2, 2, 3]。因此返回2。

分析思路

不一樣於01揹包問題的徹底揹包問題,徹底揹包問題強調了,每種物品都有無限件能夠選取,那麼咱們最終要檢查的狀態就不在是01揹包問題中的O(VN)而是擴展成O(VSUM(V/cost[i]))件物品,顯然由於擴展了可能選擇的狀況,咱們的時間複雜度激素飆升,在揹包容量很是大,而且物品的耗費很小的時候,這種算法的時間複雜度顯得力不從心。

咱們來寫一下大概思路:

  1. 最後一步

    F[n][m]表示前 n個有 多少種方式拼出m

    最後一個選上:F[n][m] = Sum(F[n-1][m-A[ki]])

    最後一個不選上:F[n][m] = F[n-1][m]

  2. 順序從小到大

  3. 邊界狀況

    F[k][0] = 1

代碼實現

public class Solution {
    /** * @param nums: an integer array and all positive numbers, no duplicates * @param target: An integer * @return: An integer */
    public int backPackIV(int[] nums, int target) {
        // write your code here
        int len = nums.length;
        if (len == 0) return 0;
        
        int[][] F = new int[len+1][target+1];
        
        
        for (int i = 0; i <= len; i++) {
            F[i][0] = 1;
        }
        
        for (int i = 1; i <= len; i++ ) {
            int item = nums[i-1];
            for (int k = 1; k <= target; k++) {
                F[i][k] = F[i-1][k];
                if (k >= item) {
                    F[i][k] += F[i][k - item];
                }
            }
        }
        
       
        return F[len][target];
    }
}
複製代碼

參考資料

  1. 揹包問題詳解:01揹包、徹底揹包、多重揹包
  2. 揹包問題九講02-徹底揹包問題總結

程序小哥介紹

考拉後端開發潮流少年White

顏值在線,衣品在線,系統開發以及維護在線。

相關文章
相關標籤/搜索