1. 程式人生 > 資訊 >谷歌、Facebook 等科技巨頭贏得喘息機會:歐盟兩大新法規被推遲

谷歌、Facebook 等科技巨頭贏得喘息機會:歐盟兩大新法規被推遲

完全揹包

題目大意:

​ 有n個物品,一個容量為m的揹包,每個物品可以選無限次,問拿到的最大總價值是多少。

思路:

dp三步走:dp陣列含義 + 初始化 + 狀態轉移

​ 1、dp陣列含義:dp[i][j]表示在前i個(包括i)物品裡選若干個把容量為j的揹包塞到塞不下所拿到的最大價值。

​ 2、初始化:前0個物品裡拿0的容量顯然dp[0][0] = 0 。

​ 3、狀態轉移:在拿第i個物品時可以取0件、2件、3件等等,直到揹包塞不下為止,所以在取k個第i個物品時要先預留出k * v的空間。所以:

dp[j] = max(dp[j] , dp[j - k * v] + k * w) ;

有01揹包程式碼:

    for(int i = 1 ; i <= n ; i ++ ){
        cin >> v >> w ;
        for(int j = m ; j >= v ; j -- )//一維滾動優化
            dp[j] = max(dp[j] , dp[j - v] + w) ;
    }
    cout<<f[m] ;

根據01揹包的取和不取 ,我們可以將完全揹包的每一個物品分成取0件、2件、3件等等,直到揹包塞不下為止。這樣樸素的想法就可以讓我們寫出完全揹包的樸素解法(n^3):

 for(int i = 1 ; i <= n ; i ++ ){
        cin>>v>>w ;
        for(int j = m ; j >= v ; j -- )
            for(int k = 1 ; j - k * v >= 0 ; k ++ )
                dp[j] = max(dp[j] , dp[j - k * v] + k * w) ;
    }
    cout<<dp[m] ;

n^2優化:

該解法對於前i個物品容量為j,有下圖中第一個式子。對於前i個物品,容量為j-v時有下圖中第二個式子。兩個式子聯立就變成了完全揹包的狀態轉移方程(綠色字)。

於是乎,程式碼進化了:

for(int i = 1 ; i <= n ; i ++ ){
    cin>>v>>w ;
    for(int j = v ; j <= m ; j ++ )
        dp[j] = max(dp[j] , dp[j - v] + w) ;
}