国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

【動態(tài)規(guī)劃之完全背包問題】完全背包問題的通用解法與優(yōu)化

這篇具有很好參考價值的文章主要介紹了【動態(tài)規(guī)劃之完全背包問題】完全背包問題的通用解法與優(yōu)化。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點(diǎn)擊"舉報違法"按鈕提交疑問。

??前面的話??

本篇文章將介紹動態(tài)規(guī)劃中的背包問題——完全背包問題,前面我們已經(jīng)介紹了0-1背包問題,其實完全背包問題就只改了0-1背包問題的一個條件,即物品可選擇次數(shù)由一次改為無數(shù)次,僅此而已,下面我們就來開始介紹完全背包問題。

??博客主頁:未見花聞的博客主頁
??歡迎關(guān)注??點(diǎn)贊??收藏??留言??
??本文由未見花聞原創(chuàng)!
??首發(fā)時間:??2022年10月22日??
??堅持和努力一定能換來詩與遠(yuǎn)方!
??推薦書籍:??《算法》,??《算法導(dǎo)論》
??參考在線編程網(wǎng)站:????途W(wǎng)??力扣
博主的碼云gitee,平常博主寫的程序代碼都在里面。
博主的github,平常博主寫的程序代碼都在里面。
??作者水平很有限,如果發(fā)現(xiàn)錯誤,一定要及時告知作者哦!感謝感謝!



【動態(tài)規(guī)劃之完全背包問題】完全背包問題的通用解法與優(yōu)化


??【問題導(dǎo)入】完全背包原題??

??題目詳情

N N N 種物品和一個容量為 C C C 的背包,每種物品都有無限件。

i i i 件物品的體積是 v [ i ] v[i] v[i] ,價值是 w [ i ] w[i] w[i] 。

求解將哪些物品裝入背包可使這些物品的費(fèi)用總和不超過背包容量,且價值總和最大。

其實就是在 0-1 背包問題的基礎(chǔ)上,增加了每件物品可以選擇多次的特點(diǎn)(在容量允許的情況下)。

示例 :

輸入: N = 2, C = 5, v = [1,2], w = [1,2]
輸出: 5
解釋: 選一件物品 1,再選兩件物品 2,可使價值最大。

??解題思路與代碼

??樸素解法

我們可以直接將0-1背包的狀態(tài)定義直接拿來使用:

狀態(tài)定義: 不妨定義 f [ i ] [ j ] f[i][j] f[i][j]表示從前 i i i件物品中選擇,容量不超過 j j j的最大價值。

確定初始狀態(tài): 當(dāng)只有一種物品選擇時,由于數(shù)量是無限的,所以盡量地選就行,不要超過容量 j j j,不妨設(shè)選這一種物品的最大件數(shù)為 k k k,則有 f [ 0 ] [ j ] = k × w [ i ] , 其中 k × v [ i ] < = j f[0][j]=k \times w[i],其中k\times v[i]<=j f[0][j]=k×w[i],其中k×v[i]<=j

狀態(tài)轉(zhuǎn)移方程推導(dǎo): 當(dāng)我們選擇第 i i i件物品的時候,我們可以選擇 0 , 1 , 2... k 0,1,2...k 0,1,2...k件,其中 k k k是最大能夠選擇的件數(shù),即在不超過容量 j j j的情況下。

當(dāng)我們不選擇第 i i i件物品時,即 k = 0 k=0 k=0, f [ i ] [ j ] = f [ i ? 1 ] [ j ] f[i][j]=f[i-1][j] f[i][j]=f[i?1][j]
當(dāng)我們選擇 1 1 1 i i i件物品時,即 k = 1 k=1 k=1, f [ i ] [ j ] = f [ i ? 1 ] [ j ? v [ i ] ] + w [ i ] f[i][j]=f[i-1][j - v[i]] + w[i] f[i][j]=f[i?1][j?v[i]]+w[i]。
當(dāng)我們選擇 2 2 2 i i i件物品時,即 k = 2 k=2 k=2 f [ i ] [ j ] = f [ i ? 1 ] [ j ? 2 ? v [ i ] ] + 2 ? w [ i ] f[i][j]=f[i-1][j - 2 * v[i]] + 2*w[i] f[i][j]=f[i?1][j?2?v[i]]+2?w[i]

當(dāng)我們選擇 k k k i i i件物品時,即 k = k k=k k=k f [ i ] [ j ] = f [ i ? 1 ] [ j ? k ? v [ i ] ] + k ? w [ i ] f[i][j]=f[i-1][j - k * v[i]]+k*w[i] f[i][j]=f[i?1][j?k?v[i]]+k?w[i]。

我們所要求的是最大的價值,所以取以上所有情況的最大值即可。

綜上所述,我們的狀態(tài)轉(zhuǎn)移方程就出來了,不妨記當(dāng)前物品的價值為:

f [ i ] [ j ] = m a x ( f [ i ? 1 ] [ j ? k ? v [ i ] ] + k ? w [ i ] ) , k = 0 , 1 , . . . f[i][j]=max(f[i-1][j-k*v[i]]+k*w[i]),k=0,1,... f[i][j]=max(f[i?1][j?k?v[i]]+k?w[i]),k=0,1,...

實現(xiàn)代碼:

    /**
     *
     * @param n 物品個數(shù)
     * @param c 背包的總?cè)萘?     * @param w 每種物品的價值
     * @param v 每種物品的容量
     * @return 能將物品放進(jìn)背包的最大價值
     */
    public int cknapsack1(int n, int c, int[] w, int[] v) {
        //狀態(tài)定義f[i][j]表示最大價值
        int[][] f = new int[n][c + 1];
        //確定初始狀態(tài)
        for (int j = 1; j <= c; j++) {
            int k = j / v[0];
            f[0][j] = k * w[0];
        }
        //狀態(tài)轉(zhuǎn)移f[i][j]=max(f[i-1][j - k * v[i]]+k*w[i]
        for (int i = 1; i < n; i++) {
            int val = w[i];
            for (int j = 1; j <= c; j++) {
                int cur = 0;
                for (int k = 0; j >= k * v[i]; k++) {
                    int t = f[i - 1][j - k * v[i]] + k * val;
                    cur = Math.max(t, cur);
                }
                f[i][j] = cur;
            }
        }
        return f[n - 1][c];
    }

時間復(fù)雜度: O ( n ? c ? k ) O(n*c*k) O(n?c?k), k k k的值不會大于 c c c,因為最低物品價值為 1 1 1,最多選擇的件數(shù)不會超過 c c c
空間復(fù)雜度: O ( n ? c ) O(n*c) O(n?c)

??滾動數(shù)組優(yōu)化空間

根據(jù)觀察我們知道第 i i i行的狀態(tài)僅依賴與第 i ? 1 i-1 i?1行的狀態(tài),因此我們可以使用滾動數(shù)組進(jìn)行優(yōu)化。

實現(xiàn)代碼:

    /**
     *
     * @param n 物品個數(shù)
     * @param c 背包的總?cè)萘?     * @param w 每種物品的價值
     * @param v 每種物品的容量
     * @return 能將物品放進(jìn)背包的最大價值
     */
    public int cknapsack2(int n, int c, int[] w, int[] v) {
        //狀態(tài)定義f[i][j]表示最大價值 滾動數(shù)組優(yōu)化
        int[][] f = new int[2][c + 1];
        //確定初始狀態(tài)
        for (int j = 1; j <= c; j++) {
            int k = j / v[0];
            f[0][j] = k * w[0];
        }
        //狀態(tài)轉(zhuǎn)移f[i][j]=max(f[i-1][j - k * v[i]]+k*w[i]
        for (int i = 1; i < n; i++) {
            int val = w[i];
            int ci = i & 1;
            int pi = (i - 1) & 1;
            for (int j = 1; j <= c; j++) {
                int cur = 0;
                for (int k = 0; j >= k * v[i]; k++) {
                    int t = f[pi][j - k * v[i]] + k * val;
                    cur = Math.max(t, cur);
                }
                f[ci][j] = cur;
            }
        }
        return f[(n - 1) & 1][c];
    }

對于時空復(fù)雜度,只是優(yōu)化了空間而已,所以時間復(fù)雜度不發(fā)生改變,空間復(fù)雜度優(yōu)化到 O ( c ) O(c) O(c)。
時間復(fù)雜度: O ( n ? c ? k ) O(n*c*k) O(n?c?k) k k k的值不會大于 c c c,因為最低物品價值為 1 1 1,最多選擇的件數(shù)不會超過 c c c。
空間復(fù)雜度: O ( c ) O(c) O(c)

??一維數(shù)組優(yōu)化空間

首先我們對狀態(tài)轉(zhuǎn)移方程進(jìn)行一個簡單的推導(dǎo):

f [ i ] [ j ] = m a x ( f [ i ? 1 ] [ j ] , f [ i ? 1 ] [ j ? v [ i ] ] + w [ i ] , f [ i ? 1 ] [ j ? 2 ? v [ i ] ] + 2 ? w [ i ] , . . . , f [ i ? 1 ] [ j ? k ? v [ i ] ] + k ? w [ i ] ) f[i][j]=max(f[i-1][j],f[i-1][j-v[i]]+w[i],f[i-1][j-2*v[i]]+2*w[i],...,f[i-1][j-k*v[i]]+k*w[i]) f[i][j]=max(f[i?1][j],f[i?1][j?v[i]]+w[i],f[i?1][j?2?v[i]]+2?w[i],...,f[i?1][j?k?v[i]]+k?w[i])

f [ i ] [ j ? v [ i ] ] = m a x ( f [ i ? 1 ] [ j ? v [ i ] ] , f [ i ? 1 ] [ j ? 2 ? v [ i ] ] + w [ i ] , f [ i ? 1 ] [ j ? 3 ? v [ i ] ] + 2 ? w [ i ] . . . , f [ i ? 1 ] [ j ? k ? v [ i ] ] + ( k ? 1 ) ? w [ i ] ) f[i][j-v[i]]=max(f[i-1][j-v[i]],f[i-1][j-2*v[i]]+w[i],f[i-1][j-3*v[i]]+2*w[i]...,f[i-1][j-k*v[i]]+(k-1)*w[i]) f[i][j?v[i]]=max(f[i?1][j?v[i]],f[i?1][j?2?v[i]]+w[i],f[i?1][j?3?v[i]]+2?w[i]...,f[i?1][j?k?v[i]]+(k?1)?w[i])

其中 k ? v [ i ] < = j k*v[i]<=j k?v[i]<=j。

通過觀察上面兩個狀態(tài)的式子,我們發(fā)現(xiàn)后面一部分式子是差了一個 w [ i ] w[i] w[i]如下圖:

【動態(tài)規(guī)劃之完全背包問題】完全背包問題的通用解法與優(yōu)化

所以我們可以進(jìn)一步優(yōu)化狀態(tài)轉(zhuǎn)移方程,即:

f [ i ] [ j ] = m a x ( f [ i ? 1 ] [ j ] , f [ i ] [ j ? v [ i ] ] + w [ i ] ) f[i][j]=max(f[i-1][j],f[i][j-v[i]]+w[i]) f[i][j]=max(f[i?1][j],f[i][j?v[i]]+w[i])

對于新推導(dǎo)出來的狀態(tài)轉(zhuǎn)移方程,它的狀態(tài)轉(zhuǎn)移僅僅只依賴與上一行同列狀態(tài)與同一行元素前面的元素,所以我們可以將原來的二維數(shù)組優(yōu)化為一維,由于它只依賴左邊與正上方的元素,我們可以采取從小到大遍歷背包容量狀態(tài)來求背包中所放物品最大值。

【動態(tài)規(guī)劃之完全背包問題】完全背包問題的通用解法與優(yōu)化

只保留【背包容量】維度,狀態(tài)轉(zhuǎn)移方程為:

f [ j ] = m a x ( f [ j ] , f [ j ? v [ i ] ] + w [ i ] ) f[j]=max(f[j],f[j-v[i]]+w[i]) f[j]=max(f[j],f[j?v[i]]+w[i])

實現(xiàn)代碼:

    /**
     *
     * @param n 物品個數(shù)
     * @param c 背包的總?cè)萘?     * @param w 每種物品的價值
     * @param v 每種物品的容量
     * @return 能將物品放進(jìn)背包的最大價值
     */
    public int cknapsack3(int n, int c, int[] w, int[] v) {
        //狀態(tài)定義f[i][j]表示最大價值 一維數(shù)組優(yōu)化
        int[] f = new int[c + 1];
        //確定初始狀態(tài)f[0]=0
        //狀態(tài)轉(zhuǎn)移
        for (int i = 0; i < n; i++) {
            for (int j = 0; j <= c; j++) {
                //不選擇物品
                int nopt = f[j];
                //選擇物品
                int opt = j >= v[i] ? f[j - v[i]] + w[i] : nopt;

                f[j] = Math.max(opt, nopt);
            }
        }
        return f[c];
    }

時間復(fù)雜度: O ( n ? c ) O(n*c) O(n?c)
空間復(fù)雜度: O ( c + 1 ) O(c+1) O(c+1)

??總結(jié)

以上我們介紹了【完全背包問題】的樸素解法和優(yōu)化方案,其中一維優(yōu)化是最復(fù)雜的,因為使用了一些數(shù)學(xué)上的推導(dǎo),比較抽象,不是特別容易理解,我建議自己嘗試推導(dǎo)一遍,這樣能夠更快的理解并且更深刻。
相比于0-1背包問題的優(yōu)化,形式上,我們只需要將 01 背包問題的「一維空間優(yōu)化」解法中的「容量維度」遍歷方向從「從大到小 改為 從小到大」就可以解決完全背包問題。
但本質(zhì)是因為兩者進(jìn)行狀態(tài)轉(zhuǎn)移時依賴了不同的格子:
0 -1 背包依賴的是「上一行正上方的格子」和「上一行左邊的格子」。
完全背包依賴的是「上一行正上方的格子」和「本行左邊的格子」。


覺得文章寫得不錯的老鐵們,點(diǎn)贊評論關(guān)注走一波!謝謝啦!

【動態(tài)規(guī)劃之完全背包問題】完全背包問題的通用解法與優(yōu)化文章來源地址http://www.zghlxwxcb.cn/news/detail-420853.html

到了這里,關(guān)于【動態(tài)規(guī)劃之完全背包問題】完全背包問題的通用解法與優(yōu)化的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點(diǎn)擊違法舉報進(jìn)行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • 動態(tài)規(guī)劃-背包問題-完全背包

    對比01背包,完全背包中的每件物品有無數(shù)件。 也就是說,每件物品可以拿0,1,…,k,…件。 dp[i][j]表示前i種物品,體積為j時的最大價值 對于第i件物品: 不拿:dp[i][j]?dp[i-1][j] 拿一件:dp[i][j]?dp[i-1][j-w[i]]+v[i] 拿兩件:dp[i][j]?dp[i-1][j-2w[i]]+2v[i] … 拿k件:dp[i]][j]?dp[i

    2024年04月08日
    瀏覽(20)
  • 完全背包&多重背包問題(動態(tài)規(guī)劃)

    完全背包問題: 每個物品使用次數(shù)沒有限制,與0-1背包的不同之處在于 遍歷背包的順序 是正序。 多重背包問題: 與完全背包的區(qū)別在于,每一種物品是有個數(shù)限制的,不能無限選擇。這篇博客講解的非常詳細(xì),可以參考學(xué)習(xí): 多重背包問題---超詳細(xì)講解+優(yōu)化(不懂你揍我

    2024年04月10日
    瀏覽(24)
  • 動態(tài)規(guī)劃之背包問題——完全背包

    算法相關(guān)數(shù)據(jù)結(jié)構(gòu)總結(jié): 序號 數(shù)據(jù)結(jié)構(gòu) 文章 1 動態(tài)規(guī)劃 動態(tài)規(guī)劃之背包問題——01背包 動態(tài)規(guī)劃之背包問題——完全背包 動態(tài)規(guī)劃之打家劫舍系列問題 動態(tài)規(guī)劃之股票買賣系列問題 動態(tài)規(guī)劃之子序列問題 算法(Java)——動態(tài)規(guī)劃 2 數(shù)組 算法分析之?dāng)?shù)組問題 3 鏈表 算法

    2024年02月03日
    瀏覽(27)
  • Python 算法基礎(chǔ)篇:背包問題的動態(tài)規(guī)劃解法

    背包問題是計算機(jī)科學(xué)中一個重要的組合優(yōu)化問題,動態(tài)規(guī)劃是解決該問題的高效算法技術(shù)。本篇博客將重點(diǎn)介紹背包問題的動態(tài)規(guī)劃解法,包括狀

    2024年02月16日
    瀏覽(26)
  • 動態(tài)規(guī)劃——完全背包問題

    動態(tài)規(guī)劃——完全背包問題

    由于本人實力尚淺,接觸算法沒多久,寫這篇blog僅僅是想要提升自己對算法的理解,如果各位讀者發(fā)現(xiàn)什么錯誤,懇請指正,希望和大家一起進(jìn)步。(●’?’●) 了解完全背包問題前可以先去看看01背包問題(良心正解),先了解這個基礎(chǔ)問題會更有利于你了解下面的完全背

    2024年02月04日
    瀏覽(29)
  • 動態(tài)規(guī)劃:完全背包問題

    動態(tài)規(guī)劃:完全背包問題

    ACwing #3. 完全背包問題 完全背包問題和01背包問題很相似。 01背包問題每個物品只能選一個,而完全背包問題每個物品可以選無限次。 DP問題的關(guān)鍵是找到狀態(tài)轉(zhuǎn)移方程: ①定義f[i][j]表示從前 i 個物品中選擇,體積為 j 的時候的最大價值。 ②那么轉(zhuǎn)移方程f[i][j] = max(f[i - 1][j

    2023年04月19日
    瀏覽(25)
  • 算法系列--動態(tài)規(guī)劃--背包問題(3)--完全背包介紹

    算法系列--動態(tài)規(guī)劃--背包問題(3)--完全背包介紹

    ??\\\"Su7\\\"?? 作者:Lvzi 文章主要內(nèi)容:算法系列–動態(tài)規(guī)劃–背包問題(3)–完全背包介紹 大家好,今天為大家?guī)淼氖?算法系列--動態(tài)規(guī)劃--背包問題(3)--完全背包介紹 鏈接: 完全背包 可以發(fā)現(xiàn)完全背包問題和01背包問題還是特比相似的 分析: 完全背包問題 是 01背包問題 的推廣

    2024年04月25日
    瀏覽(28)
  • 動態(tài)規(guī)劃完全背包問題-java

    動態(tài)規(guī)劃完全背包問題-java

    完全背包問題跟01背包問題思路大致一樣,只不過對于物品的拿取次數(shù)不在限制,我們只需要考慮這點(diǎn)即可。 文章目錄 前言 一、什么是完全背包問題? 二、問題模擬 1.樣例數(shù)據(jù) 2.算法思路 三、代碼如下 1.代碼如下(示例): 2.讀入數(shù) 3.代碼運(yùn)行結(jié)果 總結(jié) 完全背包問題跟

    2024年04月26日
    瀏覽(24)
  • 動態(tài)規(guī)劃-----背包類問題(0-1背包與完全背包)詳解

    動態(tài)規(guī)劃-----背包類問題(0-1背包與完全背包)詳解

    目錄 什么是背包問題? 動態(tài)規(guī)劃問題的一般解決辦法: 0-1背包問題: 0 - 1背包類問題? 分割等和子集:? 完全背包問題:? 完全背包類問題 零錢兌換II: 背包問題(Knapsack problem)是一種組合優(yōu)化的NP完全問題。 問題可以描述為:給定一組物品,每種物品都有自己的重量和價格

    2024年04月17日
    瀏覽(29)
  • 動態(tài)規(guī)劃:完全背包問題----中專生刷算法

    動態(tài)規(guī)劃:完全背包問題----中專生刷算法

    需要基礎(chǔ):閆氏dp分析法,01背包問題 先去看一下01背包問題,再看完全背包 動態(tài)規(guī)劃:選擇dp及優(yōu)化01背包問題-CSDN博客 做過01背包問題的同學(xué)會發(fā)現(xiàn),完全背包問題的代碼 在01背包基礎(chǔ)上改動很小,但是里面的思想,有很大差距 題目 有 N 種物品和一個容量是 V的背包,每種物品

    2024年04月16日
    瀏覽(36)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包