背包問題總結(jié)

技術(shù)交流QQ群:1027579432口四,歡迎你的加入窃植!

歡迎關(guān)注我的微信公眾號:CurryCoder的程序人生

1. 01背包問題

  • 01背包的算法思想


    01背包.jpg
  • 01背包的代碼框架
    #include <iostream>
    #include <vector>
    #include <string>
    #include <algorithm>
    
    using namespace std;
    
    
    const int N = 1010;
    
    int n, m;  // n表示所有物品的個數(shù)  m表示背包的容量
    int v[N], w[N];  // v表示第i件物品的體積  w表示第i件物品的價值
    int f[N][N];  // 所有狀態(tài)
    
    
    int main(){
        cin >> n >> m;
        for(int i = 1; i <= n; i++) cin >> v[i] >> w[i];
        
        // f[0][0~m] = 0
    
        for(int i = 1; i <= n; i++){  // 枚舉所有的物品
            for(int j = 0; j <= m; j++){  // 枚舉所有的體積
                f[i][j] = f[i-1][j];
                if(j >= v[i]) f[i][j] = max(f[i][j], f[i-1][j-v[i]] + w[i]);  // 注意此處的判斷
            }
        }
        cout << f[n][m] << endl;
        return 0;
    }
    
  • 優(yōu)化方法---優(yōu)化成一維數(shù)組來表述集合
    #include <iostream>
    #include <vector>
    #include <string>
    #include <algorithm>
    
    using namespace std;
    
    
    const int N = 1010;
    
    int n, m;  // n表示所有物品的個數(shù)  m表示背包的容量
    int v[N], w[N];  // v表示第i件物品的體積  w表示第i件物品的價值
    int f[N];  // 所有狀態(tài)
    
    
    int main(){
        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--){  // 枚舉所有的體積
                f[j] = max(f[j], f[j-v[i]] + w[i]);  // 注意此處的判斷
            }
        }
        cout << f[m] << endl;
        return 0;
    }
    

2. 完全背包問題

  • 完全背包的算法思想


    完全背包.jpg
  • 完全背包的代碼框架---樸素方法
    #include <iostream>
    #include <vector>
    #include <string>
    #include <algorithm>
    
    using namespace std;
    
    
    const int N = 1010;
    
    int n, m;  // n表示所有物品的個數(shù)  m表示背包的容量
    int v[N], w[N];  // v表示第i件物品的體積  w表示第i件物品的價值
    int f[N][N];  // 所有狀態(tài)
    
    
    int main(){
        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 = 0; j <= m; j++){
                for(int k = 0; k * v[i] <= j; k++){
                    f[i][j] = max(f[i][j], f[i-1][j - v[i] * k] + k * w[i]);
                }
            }
        }
        cout << f[n][m] << endl;
        return 0;
    }
    
  • 優(yōu)化方法
    #include <iostream>
    #include <vector>
    #include <string>
    #include <algorithm>
    
    using namespace std;
    
    
    const int N = 1010;
    
    int n, m;  // n表示所有物品的個數(shù)  m表示背包的容量
    int v[N], w[N];  // v表示第i件物品的體積  w表示第i件物品的價值
    int f[N][N];  // 所有狀態(tài)
    
    
    int main(){
        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 = 0; j <= m; j++){
                f[i][j] = f[i-1][j];
                if(j >= v[i]) f[i][j] = max(f[i][j], f[i][j-v[i]] + w[i]);
            }
        }
        cout << f[n][m] << endl;
        return 0;
    }
    

3.多重背包問題

  • 多重背包的算法思想


    多重背包.jpg
  • 多重背包的算法框架---樸素方法
    #include <iostream>
    #include <vector>
    #include <string>
    #include <algorithm>
    
    using namespace std;
    
    
    const int N = 110;
    
    int n, m;  // n表示所有物品的個數(shù)  m表示背包的容量
    int v[N], w[N], s[N];  // v表示第i件物品的體積  w表示第i件物品的價值,s[i]表示每件物品最多有s[i]個
    int f[N][N];  // 所有狀態(tài)
    
    
    int main(){
        cin >> n >> m;
        for(int i = 1; i <= n; i++) cin >> v[i] >> w[i] >> s[i];
        
        for(int i = 1; i <= n; i++)   // 枚舉所有物品
            for(int j = 0; j <= m; j++)  // 枚舉所有體積
                for(int k = 0; k <= s[i] && k * v[i] <= j; k++) // k:表示每件物品的個數(shù)最多有s[i]個
                    f[i][j] = max(f[i][j], f[i - 1][j - v[i] * k] + w[i] * k);
    
        cout << f[n][m] << endl;
        return 0;
    }
    
  • 優(yōu)化方法--二進制優(yōu)化方法
    #include <iostream>
    #include <vector>
    #include <string>
    #include <algorithm>
    
    using namespace std;
    
    
    const int N = 25000, M = 2010;
    
    int n, m;  // n表示所有物品的個數(shù)  m表示背包的容量
    int v[N], w[N], s[N];  // v表示第i件物品的體積  w表示第i件物品的價值,s[i]表示每件物品最多有s[i]個
    int f[N];  // 所有狀態(tài)
    
    
    int main(){
        cin >> n >> m;
        int cnt = 0;
        for(int i = 1; i <= n; i++)
        {
            int a, b, s; // 體積 價值 個數(shù)
            cin >> a >> b >> s;
            int k = 1;  // 多重背包的二進制優(yōu)化方法
            while(k <= s){
                cnt++;
                v[cnt] = a * k;
                w[cnt] = b * k;
                s -= k;
                k *= 2;
            }
            // s[i]中的剩余部分
            if(s > 0){
                cnt++;
                v[cnt] = a * s;
                w[cnt] = b * s;
            }
        }
    
        // 優(yōu)化版本的01背包問題
        n = cnt;
        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]);
            }
        }
        cout << f[m] << endl;
        return 0;
    }
    

4.分組背包問題

  • 分組背包的算法思想


    分組背包.jpg
  • 分組背包的算法框架---優(yōu)化方法
    #include <iostream>
    #include <vector>
    #include <string>
    #include <algorithm>
    
    using namespace std;
    
    
    const int N = 110;
    
    int n, m;  // n表示所有物品的個數(shù)  m表示背包的容量
    int v[N][N], w[N][N], s[N];  // v表示第i件物品的體積  w表示第i件物品的價值, S[i]:每組中物品的個數(shù)
    int f[N];  // 從兩維優(yōu)化成一維
    
    
    int main(){
        cin >> n >> m;
        for(int i = 1; i <= n; i++)
        {
            cin >> s[i];
            for(int j = 0; j < s[i]; j++) 
                cin >> v[i][j] >> w[i][j];
        }
    
        for(int i = 1; i <= n; i++)  // 枚舉每一組
            for(int j = m; j >= 0; j--)  // 改成一維表示狀態(tài)時,從大到小來枚舉所有體積!
                for(int k = 0; k < s[i]; k++)  // 枚舉每組中每一個物品
                    if(v[i][k] <= j) f[j] = max(f[j], f[j - v[i][k]] + w[i][k]);  // v[i][k]:第i組中的第k個物品
    
        cout << f[m] << endl;
        return 0;
    }
    
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市骇笔,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌嚣崭,老刑警劉巖笨触,帶你破解...
    沈念sama閱讀 222,627評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異雹舀,居然都是意外死亡芦劣,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,180評論 3 399
  • 文/潘曉璐 我一進店門说榆,熙熙樓的掌柜王于貴愁眉苦臉地迎上來虚吟,“玉大人,你說我怎么就攤上這事签财〈浚” “怎么了?”我有些...
    開封第一講書人閱讀 169,346評論 0 362
  • 文/不壞的土叔 我叫張陵唱蒸,是天一觀的道長邦鲫。 經(jīng)常有香客問我,道長神汹,這世上最難降的妖魔是什么庆捺? 我笑而不...
    開封第一講書人閱讀 60,097評論 1 300
  • 正文 為了忘掉前任,我火速辦了婚禮屁魏,結(jié)果婚禮上疼燥,老公的妹妹穿的比我還像新娘。我一直安慰自己蚁堤,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 69,100評論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著披诗,像睡著了一般撬即。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上呈队,一...
    開封第一講書人閱讀 52,696評論 1 312
  • 那天剥槐,我揣著相機與錄音,去河邊找鬼宪摧。 笑死粒竖,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的几于。 我是一名探鬼主播蕊苗,決...
    沈念sama閱讀 41,165評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼沿彭!你這毒婦竟也來了朽砰?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 40,108評論 0 277
  • 序言:老撾萬榮一對情侶失蹤喉刘,失蹤者是張志新(化名)和其女友劉穎瞧柔,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體睦裳,經(jīng)...
    沈念sama閱讀 46,646評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡造锅,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,709評論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了廉邑。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片哥蔚。...
    茶點故事閱讀 40,861評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖鬓催,靈堂內(nèi)的尸體忽然破棺而出肺素,到底是詐尸還是另有隱情,我是刑警寧澤宇驾,帶...
    沈念sama閱讀 36,527評論 5 351
  • 正文 年R本政府宣布倍靡,位于F島的核電站,受9級特大地震影響课舍,放射性物質(zhì)發(fā)生泄漏塌西。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 42,196評論 3 336
  • 文/蒙蒙 一筝尾、第九天 我趴在偏房一處隱蔽的房頂上張望捡需。 院中可真熱鬧,春花似錦筹淫、人聲如沸站辉。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,698評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽饰剥。三九已至殊霞,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,804評論 1 274
  • 我被黑心中介騙來泰國打工惯退, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人祝钢。 一個月前我還...
    沈念sama閱讀 49,287評論 3 379
  • 正文 我出身青樓,卻偏偏與公主長得像若厚,于是被迫代替她去往敵國和親拦英。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,860評論 2 361

推薦閱讀更多精彩內(nèi)容

  • 在C語言中,五種基本數(shù)據(jù)類型存儲空間長度的排列順序是: A)char B)char=int<=float C)ch...
    夏天再來閱讀 3,352評論 0 2
  • mean to add the formatted="false" attribute?.[ 46% 47325/...
    ProZoom閱讀 2,701評論 0 3
  • 樹形動態(tài)規(guī)劃盹沈,顧名思義就是樹+DP龄章,先分別回顧一下基本內(nèi)容吧:動態(tài)規(guī)劃:問題可以分解成若干相互聯(lián)系的階段,在每一個...
    Mr_chong閱讀 1,491評論 0 2
  • -01- 高考結(jié)束的那年暑假乞封,我沒有跟大部分人一樣做裙,選擇自己出去找個工廠打工,而是跟著兩位哥哥和父母去了工地肃晚。 很...
    林辰砂閱讀 490評論 7 7
  • 文/字芽 最近又有朋友麻煩我?guī)兔χ匮b下系統(tǒng),我便想應(yīng)該寫篇文章給他晋修。俗話說的好吧碾,授人于魚不如授人于漁,這里我便把我...
    字芽閱讀 56,713評論 210 2,556