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

動(dòng)態(tài)規(guī)劃——01背包問題

這篇具有很好參考價(jià)值的文章主要介紹了動(dòng)態(tài)規(guī)劃——01背包問題。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

寫在前面

由于本人實(shí)力尚淺,接觸算法沒多久,寫這篇blog僅僅是想要提升自己對(duì)算法的理解,如果各位讀者發(fā)現(xiàn)什么錯(cuò)誤,懇請(qǐng)指正,希望和大家一起進(jìn)步。(●’?’●)

DP(動(dòng)態(tài)規(guī)劃)核心講解

動(dòng)態(tài)規(guī)劃——01背包問題,數(shù)據(jù)結(jié)構(gòu)與算法,# 動(dòng)態(tài)規(guī)劃,動(dòng)態(tài)規(guī)劃,算法,c++
狀態(tài)表示:用一個(gè)數(shù)組f[][](數(shù)組可能是一維也可能是二維,根據(jù)具體題目具體分析)來表示某個(gè)集合,這個(gè)集合表示所有的做法,集合存的值就是對(duì)應(yīng)做法的屬性(一般是max,min,count)(換句話說:f[i][j]表示在限制i,j下做法的屬性)
狀態(tài)轉(zhuǎn)移:本質(zhì)上是一個(gè)優(yōu)化的過程,就是不斷更新狀態(tài)。

01背包問題

題目

動(dòng)態(tài)規(guī)劃——01背包問題,數(shù)據(jù)結(jié)構(gòu)與算法,# 動(dòng)態(tài)規(guī)劃,動(dòng)態(tài)規(guī)劃,算法,c++

思路

重要變量說明:
f[][[]:用于狀態(tài)表示;
w[]:記錄每個(gè)物品的價(jià)值;
v][]:記錄每個(gè)物品的體積;

  1. 定義二維數(shù)組f[][],其中f[i][j]表示在前i個(gè)物品,背包容積為j的限制下所能裝下的最大價(jià)值。這里的f[i][j]就是做法的集合,f[i][j]的值就是最大價(jià)值即屬性。
  2. i=1開始枚舉,對(duì)于第i個(gè)物品,都有選和不選兩種選擇:
    • 如果不選第i個(gè)物品,那么狀態(tài)轉(zhuǎn)移方程為f[i][j]=f[i-1][j]
    • 如果選擇第i個(gè)物品,那么狀態(tài)轉(zhuǎn)移方程為f[i][j]=f[i-1][j-v[i]]+w[i]
  3. 我們因?yàn)橐笞畲髢r(jià)值,所以對(duì)上面兩種情況去max即可

代碼(不優(yōu)化版,二維數(shù)組)

#include<iostream>

using namespace std;
const int N=1010;
int f[N][N],v[N],w[N];

int main()
{
    int n,V;
    cin>>n>>V;
    for(int i=1;i<=n;i++)   
        cin>>v[i]>>w[i];
    for(int i=1;i<=n;i++)       //從第一個(gè)物品開始選,直到最后一個(gè)物品結(jié)束
        for(int j=1;j<=V;j++)       //從最小的體積開始,直到背包的最大的容積
        {
            if(j-v[i]>=0)       //可以裝第i個(gè)物品
                f[i][j]=f[i-1][j-v[i]]+w[i];        //狀態(tài)轉(zhuǎn)移
            f[i][j]=max(f[i][j],f[i-1][j]);     //狀態(tài)轉(zhuǎn)移,兩種情況取最大值
        }
    cout<<f[n][V]<<endl;
    return 0;
}

優(yōu)化1(滾動(dòng)數(shù)組)

注意: 這里優(yōu)化的的是空間而不是時(shí)間

思路

我們注意到其實(shí)上面寫的f[i][j]其實(shí)每次計(jì)算只是用到了第i層和第i-1層,所以我們數(shù)組的第一維其實(shí)只用開兩個(gè)即可。

代碼
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 1010;
int v[N];
int w[N];
int f[N][N];
int main(){
    int n,m;
    scanf("%d%d",&n,&m);
    for(int i = 1;i <= n;i ++) scanf("%d%d",&v[i],&w[i]);
    for(int i = 1;i <= n;i ++){
        for(int j = 0;j <= m;j ++){
            f[i % 2][j] = f[(i - 1) % 2][j];
            if(j >= v[i]) f[i % 2][j] = max(f[i % 2][j],f[(i - 1) % 2][j - v[i]] + w[i]);
        }
    }
    printf("%d",f[n % 2][m]);
    return 0;
}

優(yōu)化2(一維數(shù)組)

我們可以把二維數(shù)組優(yōu)化到一維數(shù)組
為什么可以這樣變形呢?我們定義的狀態(tài)f[i][j]可以求得任意合法的i與j最優(yōu)解,但題目只需要求得最終狀態(tài)f[n][m],因此我們只需要一維的空間來更新狀態(tài)

思路
  1. 定義f[]表示狀態(tài),f[j]表示在N個(gè)物品,背包容積為j下所能裝下的最大價(jià)值。
  2. 也還是從i開始枚舉,表示選與不選第i個(gè)物品。
注意

我們要逆序枚舉背包容積,即每次循環(huán)從背包的最大容積開始枚舉。
**原因如下:**在二維情況下,狀態(tài)f[i][j]是由上一輪i - 1的狀態(tài)得來的,f[i][j]f[i - 1][j]是獨(dú)立的。而優(yōu)化到一維后,如果我們還是正序,則有f[較小體積]更新到f[較大體積],則有可能本應(yīng)該用第i-1輪的狀態(tài)卻用的是第i輪的狀態(tài)。
**簡(jiǎn)單來說:**簡(jiǎn)單來說,一維情況正序更新狀態(tài)f[j]需要用到前面計(jì)算的狀態(tài)已經(jīng)被「污染」,逆序則不會(huì)有這樣的問題。
相信即使我上面解釋的已經(jīng)夠詳細(xì)了,但是有些讀者沒有看明白,沒關(guān)系,我下面舉個(gè)栗子就非常清楚了。
栗子: 假設(shè)總共有三件物品,背包容積為10。

物品 體積 價(jià)值
1 4 5
2 5 6
3 6 7
    如果 j 層循環(huán)是遞增的: 
    for (int i = 1; i <= n; i++) {
        for (int j = v[i]; j <= m; j++) {
            f[j] = max(f[j], f[j - v[i]] + w[i]);
        }
    }

模擬過程如下

    當(dāng)還未進(jìn)入循環(huán)時(shí):
    f[0] = 0;  f[1] = 0;  f[2] = 0;  f[3] = 0;  f[4] = 0;  
    f[5] = 0;  f[6] = 0;  f[7] = 0;  f[8] = 0;  f[9] = 0; f[10] = 0;
    當(dāng)進(jìn)入循環(huán) i == 1 時(shí):
    f[4] = max(f[4], f[0] + 5);max(0, 5) = 5; 即f[4] = 5;
    f[5] = max(f[5], f[1] + 5);max(0, 5) = 5; 即f[5] = 5;
    f[6] = max(f[6], f[2] + 5);max(0, 5) = 5; 即f[6] = 5;
    f[7] = max(f[7], f[3] + 5);max(0, 5) = 5; 即f[7] = 5;
    重點(diǎn)來了!??!
    f[8] = max(f[8], f[4] + 5);max(0, 5 + 5) = 10; 即f[8] = 10;
    這里就已經(jīng)出錯(cuò)了
    因?yàn)榇藭r(shí)處于 i == 1 這一層,即物品只有一件,不存在單件物品滿足價(jià)值為10
    所以已經(jīng)出錯(cuò)了。

    如果 j 層循環(huán)是逆序的:
    for (int i = 1; i <= n; i++) {
        for (int j = m; j >= v[i]; j--) {
            f[j] = max(f[j], f[j - v[i]] + w[i]);
        }
    }

模擬過程如下

    當(dāng)還未進(jìn)入循環(huán)時(shí):
    f[0] = 0;  f[1] = 0;  f[2] = 0;  f[3] = 0;  f[4] = 0;  
    f[5] = 0;  f[6] = 0;  f[7] = 0;  f[8] = 0;  f[9] = 0; f[10] = 0;
    當(dāng)進(jìn)入循環(huán) i == 1 時(shí):w[i] = 5; v[i] = 4;
    j = 10:f[10] = max(f[10], f[6] + 5);max(0, 5) = 5; 即f[10] = 5;
    j = 9 :f[9] = max(f[9], f[5] + 5);max(0, 5) = 5; 即f[9] = 5;
    j = 8 :f[8] = max(f[8], f[4] + 5);max(0, 5) = 5; 即f[8] = 5;
    j = 7 :f[7] = max(f[7], f[3] + 5);max(0, 5) = 5; 即f[7] = 5;
    j = 6 :f[6] = max(f[6], f[2] + 5);max(0, 5) = 5; 即f[6] = 5;
    j = 5 :f[5] = max(f[5], f[1] + 5);max(0, 5) = 5; 即f[5] = 5;
    j = 4 :f[6] = max(f[4], f[0] + 5);max(0, 5) = 5; 即f[4] = 5;
    當(dāng)進(jìn)入循環(huán) i == 2 時(shí):w[i] = 6; v[i] = 5; 
    j = 10:f[10] = max(f[10], f[5] + 6);max(5, 11) = 11; 即f[10] = 11;
    j = 9 :f[9] = max(f[9], f[4] + 6);max(5, 11) = 5; 即f[9] = 11;
    j = 8 :f[8] = max(f[8], f[3] + 6);max(5, 6) = 6; 即f[8] = 6;
    j = 7 :f[7] = max(f[7], f[2] + 6);max(5, 6) = 6; 即f[7] = 6;
    j = 6 :f[6] = max(f[6], f[1] + 6);max(5, 6) = 6; 即f[6] = 6;
    j = 5 :f[5] = max(f[5], f[0] + 6);max(5, 6) = 6; 即f[5] = 6;
    當(dāng)進(jìn)入循環(huán) i == 3 時(shí): w[i] = 7; v[i] = 6; 
    j = 10:f[10] = max(f[10], f[4] + 7);max(11, 12) = 12; 即f[10] = 12;
    j = 9 :f[9] = max(f[9], f[3] + 6);max(11, 6) = 11; 即f[9] = 11;
    j = 8 :f[8] = max(f[8], f[2] + 6);max(6, 6) = 6; 即f[8] = 6;
    j = 7 :f[7] = max(f[7], f[1] + 6);max(6, 6) = 6; 即f[7] = 6;
    j = 6 :f[6] = max(f[6], f[0] + 6);max(6, 6) = 6; 即f[6] = 6;
代碼(優(yōu)化后,一維數(shù)組)
#include<iostream>

using namespace std;
const int N=1010;
int f[N],v[N],w[N];

int main()
{
    int n,m;
    cin>>n>>m;
    for(int i=1;i<=n;i++)
        cin>>v[i]>>w[i];
    for(int i=1;i<=n;i++)
        for(int j=m;j>=v[i];j--)        //逆序,防止被數(shù)據(jù)污染
            f[j]=max(f[j],f[j-v[i]]+w[i]);
    cout<<f[m]<<endl;
    return 0;
}

???總結(jié)
“種一顆樹最好的是十年前,其次就是現(xiàn)在”
所以,
“讓我們一起努力吧,去奔赴更高更遠(yuǎn)的山海”
動(dòng)態(tài)規(guī)劃——01背包問題,數(shù)據(jù)結(jié)構(gòu)與算法,# 動(dòng)態(tài)規(guī)劃,動(dòng)態(tài)規(guī)劃,算法,c++
如果有錯(cuò)誤?,歡迎指正喲??

??如果覺得收獲滿滿,可以動(dòng)動(dòng)小手,點(diǎn)點(diǎn)贊??,支持一下喲??文章來源地址http://www.zghlxwxcb.cn/news/detail-776837.html

到了這里,關(guān)于動(dòng)態(tài)規(guī)劃——01背包問題的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

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

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

相關(guān)文章

  • 算法系列--動(dòng)態(tài)規(guī)劃--背包問題(1)--01背包介紹

    算法系列--動(dòng)態(tài)規(guī)劃--背包問題(1)--01背包介紹

    ??\\\"趁著年輕,做一些比較cool的事情\\\"?? 作者:Lvzi 文章主要內(nèi)容:算法系列–動(dòng)態(tài)規(guī)劃–背包問題(1)–01背包介紹 大家好,今天為大家?guī)淼氖?算法系列--動(dòng)態(tài)規(guī)劃--背包問題(1)--01背包介紹 背包問題是動(dòng)態(tài)規(guī)劃中經(jīng)典的一類問題,經(jīng)常在筆試面試中出現(xiàn),是非常 具有區(qū)分度 的題

    2024年04月16日
    瀏覽(93)
  • 算法學(xué)習(xí)17-動(dòng)態(tài)規(guī)劃01:背包問題

    算法學(xué)習(xí)17-動(dòng)態(tài)規(guī)劃01:背包問題

    提示:以下是本篇文章正文內(nèi)容: 提示:這里對(duì)文章進(jìn)行總結(jié): ??????

    2024年04月27日
    瀏覽(102)
  • 【動(dòng)態(tài)規(guī)劃】01背包問題——算法設(shè)計(jì)與分析

    【動(dòng)態(tài)規(guī)劃】01背包問題——算法設(shè)計(jì)與分析

    若超市允許顧客使用一個(gè)體積大小為13的背包,選擇一件或多件商品帶走,則如何選擇可以使得收益最高? 商品 價(jià)格 體積 啤酒 24 10 汽水 2 3 餅干 9 4 面包 10 5 牛奶 9 4 0-1 Knapsack Problem 輸入: quad - n n n 個(gè)商品組成集合 O O O ,每個(gè)商品有屬性價(jià)格 p i p_i p i ? 和體積 v i v_i v

    2024年02月04日
    瀏覽(85)
  • 算法分析與設(shè)計(jì)——?jiǎng)討B(tài)規(guī)劃求解01背包問題

    算法分析與設(shè)計(jì)——?jiǎng)討B(tài)規(guī)劃求解01背包問題

    假設(shè)有四個(gè)物品,如下圖,背包總?cè)萘繛?,求背包裝入哪些物品時(shí)累計(jì)的價(jià)值最多。 我們使用動(dòng)態(tài)規(guī)劃來解決這個(gè)問題,首先使用一個(gè)表格來模擬整個(gè)算法的過程。 表格中的信息表示 指定情況下能產(chǎn)生的最大價(jià)值 。例如, (4, 8)表示在背包容量為8的情況下,前四個(gè)物品的最

    2024年02月04日
    瀏覽(93)
  • 【Java實(shí)現(xiàn)】動(dòng)態(tài)規(guī)劃算法解決01背包問題

    【Java實(shí)現(xiàn)】動(dòng)態(tài)規(guī)劃算法解決01背包問題

    1、問題描述: 一個(gè)旅行者有一個(gè)最多能裝m公斤的背包,現(xiàn)在有n中物品,每件的重量分別是W1、W2、……、Wn,每件物品的價(jià)值分別為C1、C2、……、Cn, 需要將物品放入背包中,要怎么樣放才能保證背包中物品的總價(jià)值最大? 2、動(dòng)態(tài)規(guī)劃算法的概述 1)動(dòng)態(tài)規(guī)劃(Dynamic Progra

    2023年04月09日
    瀏覽(92)
  • 算法套路十四——?jiǎng)討B(tài)規(guī)劃之背包問題:01背包、完全背包及各種變形

    算法套路十四——?jiǎng)討B(tài)規(guī)劃之背包問題:01背包、完全背包及各種變形

    如果對(duì)遞歸、記憶化搜索及動(dòng)態(tài)規(guī)劃的概念與關(guān)系不太理解,可以前往閱讀算法套路十三——?jiǎng)討B(tài)規(guī)劃DP入門 背包DP介紹:https://oi-wiki.org/dp/knapsack/ 0-1背包:有n個(gè)物品,第i個(gè)物品的體積為w[i],價(jià)值為v[i],每個(gè)物品至多選一個(gè), 求體積和不超過capacity時(shí)的最大價(jià)值和,其中i從

    2024年02月10日
    瀏覽(89)
  • C++算法初級(jí)11——01背包問題(動(dòng)態(tài)規(guī)劃2)

    C++算法初級(jí)11——01背包問題(動(dòng)態(tài)規(guī)劃2)

    辰辰采藥 辰辰是個(gè)天資聰穎的孩子,他的夢(mèng)想是成為世界上最偉大的醫(yī)師。為此,他想拜附近最有威望的醫(yī)師為師。醫(yī)師為了判斷他的資質(zhì),給他出了一個(gè)難題。醫(yī)師把他帶到一個(gè)到處都是草藥的山洞里對(duì)他說:“孩子,這個(gè)山洞里有一些不同的草藥,采每一株都需要一些時(shí)

    2024年02月02日
    瀏覽(92)
  • 【算法日志】動(dòng)態(tài)規(guī)劃刷題:01背包問題,多重背包問題(day37,day38)

    【算法日志】動(dòng)態(tài)規(guī)劃刷題:01背包問題,多重背包問題(day37,day38)

    目錄 前言 目標(biāo)和(01背包) 一和零(01背包) 零錢兌換(多重背包) 排列總和(多重背包) 這兩天都是背包問題,其中的01背包的一些應(yīng)用問題需要一定的數(shù)學(xué)建模能力,需要i將實(shí)際問題簡(jiǎn)化成我們熟悉的背包問題;而這兩天的多重背包問題還算比較基礎(chǔ),但也要我明白了

    2024年02月11日
    瀏覽(95)
  • 【算法|動(dòng)態(tài)規(guī)劃 | 01背包問題No.2】AcWing 423. 采藥

    【算法|動(dòng)態(tài)規(guī)劃 | 01背包問題No.2】AcWing 423. 采藥

    個(gè)人主頁:兜里有顆棉花糖 歡迎 點(diǎn)贊?? 收藏? 留言? 加關(guān)注??本文由 兜里有顆棉花糖 原創(chuàng) 收錄于專欄【手撕算法系列專欄】【AcWing算法提高學(xué)習(xí)專欄】 ??本專欄旨在提高自己算法能力的同時(shí),記錄一下自己的學(xué)習(xí)過程,希望對(duì)大家有所幫助 ??希望我們一起努力、成

    2024年02月06日
    瀏覽(93)
  • 算法設(shè)計(jì)與分析實(shí)驗(yàn)二:動(dòng)態(tài)規(guī)劃法求解TSP問題和01背包問題

    算法設(shè)計(jì)與分析實(shí)驗(yàn)二:動(dòng)態(tài)規(guī)劃法求解TSP問題和01背包問題

    【實(shí)驗(yàn)內(nèi)容】 (1)tsp問題:利用動(dòng)態(tài)規(guī)劃算法編程求解TSP問題,并進(jìn)行時(shí)間復(fù)雜性分析。 輸入:n個(gè)城市,權(quán)值,任選一個(gè)城市出發(fā); 輸出:以表格形式輸出結(jié)果,并給出向量解和最短路徑長(zhǎng)度。 (2)01背包問題:利用動(dòng)態(tài)規(guī)劃算法編程求解0-1背包問題,并進(jìn)行時(shí)間復(fù)雜性分

    2024年02月03日
    瀏覽(20)

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

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

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

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包