自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

你覺得背包真的很簡單嗎?

開發(fā) 前端
有一個容量有限的背包,容量為w,以及m個待選擇的物品,每個只有一件。每個物品有一定的重量和價(jià)值,那么選擇哪些物品放入背包,可使選擇的物品總價(jià)值最大呢?

[[420643]]

01故事起源

有一個容量有限的背包,容量為w,以及m個待選擇的物品,每個只有一件。每個物品有一定的重量和價(jià)值,那么選擇哪些物品放入背包,可使選擇的物品總價(jià)值最大呢?

02問題解析

如果背包沒有容量限制,那肯定是把所有的物品都放入背包可使價(jià)值最大。

但現(xiàn)在背包比較小,只能選擇部分裝進(jìn)背包,比如只能放一個,那就把鉆石裝進(jìn)去。

很容易可以想到,盡量放重量小且單價(jià)高的物品,但怎么對問題進(jìn)行一個嚴(yán)謹(jǐn)?shù)慕D?,繼續(xù)往下分析。

03分析

背包有一個固定的容量,容量是1kg,或者2kg,或者3kg,其實(shí)具體的數(shù)量對問題的本質(zhì)沒有影響。

 

對于物品來說,也就分兩種情況,要么放入背包,要么不放。

有m個物品,那總共就有2^m種選擇方式,很明顯這個數(shù)量很大,所以也不可能直接把所有的選擇方式枚舉出來。

04小問題過度大問題

假設(shè)背包容量為1kg,那可裝入的最大價(jià)值就是將手表裝入,其他的也裝不下。

如果有一個更大的背包,它的容量可以看成是2個小容量的背包的總和。

但它能裝入的價(jià)值卻不能簡單的直接分解為2個小背包,因?yàn)槲锲分挥幸粋€,這會導(dǎo)致物品重復(fù)。

所以對物品也再進(jìn)行一次劃分,m個物品可以分解為m1+m2個,同時背包容量也分解為w1+w2。

再看上面左右兩邊,和原來的問題還是一樣的,本質(zhì)不變,只是變成了數(shù)據(jù)規(guī)模更小的一個子問題。如果有了子問題的答案,那是不是就可以組合成更大規(guī)模的答案了呢?

我猜這里肯定有同學(xué)會說,這樣分解的小問題一定能得到最終大問題的最優(yōu)解嗎?我們來嘗試證明一下。

05逆向思維

假設(shè)下面就是最終的最優(yōu)解選擇的物品。

如果從某個位置砍一刀分開,保證w1和w2能裝下自己這邊的最終選擇物品,那最優(yōu)解也就被分成了兩個小規(guī)模問題的最優(yōu)解。這也說明如果枚舉了所有小規(guī)模最優(yōu)解的組合方式,也一定能得到大規(guī)模的最優(yōu)解。

06算法建模

根據(jù)上面的分析,現(xiàn)在問題就變得簡單了,直接按物品和重量拆分小問題,通過小問題遞推出大問題就行了。

設(shè)f[i][j]表示前i個物品背包容量為j時,能選擇的最大價(jià)值。w[i]表示第i個物品的重量,v[i]表示第i個物品的價(jià)值。

  • 裝不下第i個物品,則f[i][j]=f[i-1][j]
  • 能裝下第i個物品,則f[i][j]=max(f[i][j],f[i-1][j-w[i]]+v[i])

那為什么只需要從前i-1個物品遞推就行了呢,因?yàn)橹恍枰幸环N情況能得到最優(yōu)解就夠了,并不需要把前面的所有劃分都枚舉出來。這其實(shí)就相當(dāng)于把i個物品劃分成i-1個物品和1個物品時的情況。前面的子問題也已經(jīng)包含在當(dāng)前的解中了。

代碼實(shí)現(xiàn)

  1. int f[101][1001], w[101], v[101]; 
  2. int n, m; 
  3. int main() { 
  4.     cin >> m >> n; 
  5.     for (int i = 1; i <= m; ++i) { 
  6.         cin >> w[i] >> v[i]; 
  7.     } 
  8.     f[0][0] = 0; 
  9.     for (int i = 1; i <= m; ++i) { 
  10.         for (int j = 0; j <= n; ++j) { 
  11.             f[i][j] = f[i - 1][j]; 
  12.             if (j >= w[i]) { 
  13.                 f[i][j] = max(f[i][j], f[i - 1][j - w[i]] + v[i]); 
  14.             } 
  15.         } 
  16.     } 
  17.     cout << f[m][n] << endl; 
  18.     return 0; 

07總結(jié)

背包在動態(tài)規(guī)劃中是一個非常重要的系列,涉及的類型和變種也非常的多,今天講的01背包是最基本的一種,不過真正理解了01背包,對后續(xù)其它的背包也才能更好的掌握。

本文原創(chuàng)作者:小K,一個思維獨(dú)特的寫手。

 

責(zé)任編輯:武曉燕 來源: 小K算法
相關(guān)推薦

2022-02-14 21:31:00

用戶身份驗(yàn)證

2022-03-04 17:21:29

Redux項(xiàng)目前端

2017-03-16 16:57:56

2024-07-15 08:02:37

2010-02-23 16:21:24

Python Win

2010-03-02 17:22:46

Android技術(shù)

2016-04-21 09:43:33

編程音樂

2018-07-09 08:35:45

Windows 10WindowsBug

2010-01-20 10:14:53

C++程序

2012-07-11 13:35:53

代碼

2017-02-07 15:25:39

5Gwifi上網(wǎng)

2022-01-10 17:18:26

框架 RPC架構(gòu)

2010-03-02 15:22:40

Android手機(jī)

2010-02-06 10:34:11

Android生命周期

2010-03-10 11:14:56

智能交換機(jī)

2010-03-17 14:50:06

智能交換機(jī)

2010-01-21 17:14:40

C++兼容

2019-11-05 09:20:06

SQLiteLinux

2011-12-02 09:29:19

2013-03-20 18:14:35

架構(gòu)架構(gòu)設(shè)計(jì)項(xiàng)目
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號