關(guān)于背包問題的一些理解和應(yīng)用
1.背包問題介紹
背包問題不單單是一個(gè)簡(jiǎn)單的算法問題,它本質(zhì)上代表了一大類問題,這類問題實(shí)際上是01線性規(guī)劃問題,其約束條件和目標(biāo)函數(shù)如下:
自從dd_engi在2007年推出《背包問題九講》之后,背包問題的主要精髓基本已道盡。本文沒有嘗試對(duì)背包問題的本質(zhì)進(jìn)行擴(kuò)展或深入挖掘,而只是從有限的理解(這里指對(duì)《背包問題九講》的理解)出發(fā),幫助讀者更快地學(xué)習(xí)《背包問題九講》中的提到的各種背包問題的主要算法思想,并通過實(shí)例解釋了相應(yīng)的算法,同時(shí)給出了幾個(gè)背包問題的經(jīng)典應(yīng)用。
2.背包問題及應(yīng)用
dd_engi在《背包問題九講》中主要提到四種背包問題,分別為:01背包問題,完全背包問題,多重背包問題,二維費(fèi)用背包問題。本節(jié)總結(jié)了這幾種背包問題,并給出了其典型的應(yīng)用以幫助讀者理解這幾種問題的本質(zhì)。
2.101背包問題
(1)問題描述
有N件物品和一個(gè)容量為V的背包。第i件物品的費(fèi)用是c[i],價(jià)值是w[i]。求解將哪些物品裝入背包可使價(jià)值總和最大。
(2)狀態(tài)轉(zhuǎn)移方程
其中,f(i,v) 表示從前i件物品選擇若干物品裝到容量為v的背包中產(chǎn)生的最大價(jià)值。當(dāng)v=0時(shí),f(i,v)初始化為0,表示題目不要求背包一定剛好裝滿,而f(i,v)=inf/-inf(正無窮或負(fù)無窮)表示題目要求背包一定要?jiǎng)偤醚b滿。下面幾種背包類似,以后不再贅述。
(3) 偽代碼
從轉(zhuǎn)移方程上可以看出,前i個(gè)物品的最優(yōu)解只依賴于前i-1個(gè)物品最優(yōu)解,而與前i-2,i-3,…各物品最優(yōu)無直接關(guān)系,可以利用這個(gè)特點(diǎn)優(yōu)化存儲(chǔ)空間,即只申請(qǐng)一個(gè)一維數(shù)組即可,算法時(shí)間復(fù)雜度(O(VN))為:
for i=1..N for v=V..0 f[v]=max{f[v],f[v-c[i]]+w[i]};
注意v的遍歷順序?。?!
下面幾種背包用到類似優(yōu)化,以后不再贅述。
(4) 舉例
V=10,N=3,c[]={3,4,5}, w={4,5,6}
(1)背包不一定裝滿
計(jì)算順序是:從右往左,自上而下:
(2)背包剛好裝滿
計(jì)算順序是:從右往左,自上而下。注意初始值,其中-inf表示負(fù)無窮
(5) 經(jīng)典題型
[1] 你有一堆石頭質(zhì)量分別為W1,W2,W3…WN.(W<=100000,N <30)現(xiàn)在需要你將石頭合并為兩堆,使兩堆質(zhì)量的差為最小。
[2] 給一個(gè)整數(shù)的集合,要把它分成兩個(gè)集合,要兩個(gè)集合的數(shù)的和最接近
[3] 有一個(gè)箱子容量為V(正整數(shù),0≤V≤20000),同時(shí)有n個(gè)物品(0小于n≤30),每個(gè)物品有一個(gè)體積(正整數(shù))。要求從n個(gè)物品中,任取若干個(gè)裝入箱內(nèi),使箱子的剩余空間為最小。
2.2完全背包問題
(1)問題描述
有N種物品和一個(gè)容量為V的背包,每種物品都有無限件可用。第i種物品的費(fèi)用是c[i],價(jià)值是w[i]。求解將哪些物品裝入背包可使這些物品的費(fèi)用總和不超過背包容量,且價(jià)值總和最大。
(2)狀態(tài)轉(zhuǎn)移方程
或者:
(3) 偽代碼
for i=1..N for v=0..V f[v]=max{f[v],f[v-c[i]]+w[i]};
注意v的遍歷順序?。?!
注意,時(shí)間復(fù)雜度仍為:O(VN).
(4) 舉例
V=10,N=3,c[]={3,4,5}, w={4,5,6}
(1)背包不一定裝滿
計(jì)算順序是:從左往右,自上而下:
(2)背包剛好裝滿
計(jì)算順序是:從左往右,自上而下。注意初始值,其中-inf表示負(fù)無窮
(5) 經(jīng)典題型
[1] 找零錢問題:有n種面額的硬幣,每種硬幣無限多,至少用多少枚硬幣表示給定的面值M?
2.3多重背包問題
(1)問題描述
有N種物品和一個(gè)容量為V的背包。第i種物品最多有n[i]件可用,每件費(fèi)用是c[i],價(jià)值是w[i]。求解將哪些物品裝入背包可使這些物品的費(fèi)用總和不超過背包容量,且價(jià)值總和最大。
(2)狀態(tài)轉(zhuǎn)移方程
(3) 解題思想
用以下方法轉(zhuǎn)化為普通01背包問題:將第i種物品分成若干件物品,其中每件物品有一個(gè)系數(shù),這件物品的費(fèi)用和價(jià)值均是原來的費(fèi)用和價(jià)值乘以這個(gè)系數(shù)。使這些系數(shù)分別為 1,2,4,…,2^(k-1),n[i]-2^k+1,且k是滿足n[i]-2^k+1>0的最大整數(shù)。例如,如果n[i]為13,就將這種 物品分成系數(shù)分別為1,2,4,6的四件物品。這種方法能保證對(duì)于0..n[i]間的每一個(gè)整數(shù),均可以用若干個(gè)系數(shù)的和表示。這個(gè)很容易證明,證明過程中用到以下定理:任何一個(gè)整數(shù)n均可以表示成:n=a0*2^0+a1*2^1+…+ak*2^k,其中ak=0或者1(實(shí)際上就是n的二進(jìn)制分解),
定理:一個(gè)正整數(shù)n可以被分解成1,2,4,…,2^(k-1),n-2^k+1(k是滿足n-2^k+1>0的最大整數(shù))的形式,且1~n之內(nèi)的所有整數(shù)均可以唯一表示成1,2,4,…,2^(k-1),n-2^k+1中某幾個(gè)數(shù)的和的形式。
該定理的證明如下:
(1) 數(shù)列1,2,4,…,2^(k-1),n-2^k+1中所有元素的和為n,所以若干元素的和的范圍為:[1, n];
(2)如果正整數(shù)t<= 2^k – 1,則t一定能用1,2,4,…,2^(k-1)中某幾個(gè)數(shù)的和表示,這個(gè)很容易證明:我們把t的二進(jìn)制表示寫出來,很明顯,t可以表示成n=a0*2^0+a1*2^1+…+ak*2^(k-1),其中ak=0或者1,表示t的第ak位二進(jìn)制數(shù)為0或者1.
(3)如果t>=2^k,設(shè)s=n-2^k+1,則t-s<=2^k-1,因而t-s可以表示成1,2,4,…,2^(k-1)中某幾個(gè)數(shù)的和的形式,進(jìn)而t可以表示成1,2,4,…,2^(k-1),s中某幾個(gè)數(shù)的和(加數(shù)中一定含有s)的形式。
(證畢!)
該算法的時(shí)間復(fù)雜度為:O(V*sum(logn[i])).
(4) 經(jīng)典題型
[1] 找零錢問題:有n種面額的硬幣,分別為a[0], a[1],…, a[n-1],每種硬幣的個(gè)數(shù)為b[0], b[1],…, b[n-1],至少用多少枚硬幣表示給定的面值M?
2.4二維費(fèi)用背包
(1)問題描述
二維費(fèi)用的背包問題是指:對(duì)于每件物品,具有兩種不同的費(fèi)用;選擇這件物品必須同時(shí)付出這兩種代價(jià);對(duì)于每種代價(jià)都有一個(gè)可付出的最大值(背包容量)。問 怎樣選擇物品可以得到最大的價(jià)值。設(shè)這兩種代價(jià)分別為代價(jià)1和代價(jià)2,第i件物品所需的兩種代價(jià)分別為a[i]和b[i]。兩種代價(jià)可付出的最大值(兩種 背包容量)分別為V和U。物品的價(jià)值為w[i]。
(2)狀態(tài)轉(zhuǎn)移方程
(3)算法思想
采用同一維情況類似的方法求解
(4)經(jīng)典題型
有2n個(gè)整數(shù),平均分成兩組,每組n個(gè)數(shù),使這兩組數(shù)的和最接近。
3.背包總結(jié)
背包問題實(shí)際上代表的是線性規(guī)劃問題,一般要考慮以下幾個(gè)因素已決定選取什么樣的算法:
(1)約束條件,有一個(gè)還是兩個(gè)或者更多個(gè),如果是一個(gè),可能是01背包,完全背包或者多重背包問題,如果有兩個(gè)約束條件,則可能是二維背包問題。
(2)優(yōu)化目標(biāo),求最大值,還是最小值,還是總數(shù)(只需將max換成sum)
(3)每種物品的個(gè)數(shù)限制,如果每種物品只有一個(gè),只是簡(jiǎn)單的01背包問題,如果個(gè)數(shù)無限制,則是完全背包問題,如果每種物品的個(gè)數(shù)有限制,則是多重背包問題。
(4)背包是否要求剛好塞滿,注意不塞滿和塞滿兩種情況下初始值不同。
4.參考資料
dd_engi:《背包問題九講》
上一篇:MFC控件之CListCtrl的應(yīng)用實(shí)例教程
欄 目:C語(yǔ)言
下一篇:算法之排序算法的算法思想和使用場(chǎng)景總結(jié)
本文標(biāo)題:關(guān)于背包問題的一些理解和應(yīng)用
本文地址:http://mengdiqiu.com.cn/a1/Cyuyan/3447.html
您可能感興趣的文章
- 01-10數(shù)據(jù)結(jié)構(gòu)課程設(shè)計(jì)- 解析最少換車次數(shù)的問題詳解
- 01-10c語(yǔ)言 跳臺(tái)階問題的解決方法
- 01-10用貪心法求解背包問題的解決方法
- 01-10深入第K大數(shù)問題以及算法概要的詳解
- 01-10深入N皇后問題的兩個(gè)最高效算法的詳解
- 01-10深入解析Linux下\r\n的問題
- 01-10數(shù)組中求第K大數(shù)的實(shí)現(xiàn)方法
- 01-10深入理解大數(shù)與高精度數(shù)的處理問題
- 01-10節(jié)序問題:解析大小的端判定
- 01-10基于c的for循環(huán)中改變變量值的問題


閱讀排行
- 1C語(yǔ)言 while語(yǔ)句的用法詳解
- 2java 實(shí)現(xiàn)簡(jiǎn)單圣誕樹的示例代碼(圣誕
- 3利用C語(yǔ)言實(shí)現(xiàn)“百馬百擔(dān)”問題方法
- 4C語(yǔ)言中計(jì)算正弦的相關(guān)函數(shù)總結(jié)
- 5c語(yǔ)言計(jì)算三角形面積代碼
- 6什么是 WSH(腳本宿主)的詳細(xì)解釋
- 7C++ 中隨機(jī)函數(shù)random函數(shù)的使用方法
- 8正則表達(dá)式匹配各種特殊字符
- 9C語(yǔ)言十進(jìn)制轉(zhuǎn)二進(jìn)制代碼實(shí)例
- 10C語(yǔ)言查找數(shù)組里數(shù)字重復(fù)次數(shù)的方法
本欄相關(guān)
- 04-02c語(yǔ)言函數(shù)調(diào)用后清空內(nèi)存 c語(yǔ)言調(diào)用
- 04-02func函數(shù)+在C語(yǔ)言 func函數(shù)在c語(yǔ)言中
- 04-02c語(yǔ)言的正則匹配函數(shù) c語(yǔ)言正則表達(dá)
- 04-02c語(yǔ)言用函數(shù)寫分段 用c語(yǔ)言表示分段
- 04-02c語(yǔ)言中對(duì)數(shù)函數(shù)的表達(dá)式 c語(yǔ)言中對(duì)
- 04-02c語(yǔ)言編寫函數(shù)冒泡排序 c語(yǔ)言冒泡排
- 04-02c語(yǔ)言沒有round函數(shù) round c語(yǔ)言
- 04-02c語(yǔ)言分段函數(shù)怎么求 用c語(yǔ)言求分段
- 04-02C語(yǔ)言中怎么打出三角函數(shù) c語(yǔ)言中怎
- 04-02c語(yǔ)言調(diào)用函數(shù)求fibo C語(yǔ)言調(diào)用函數(shù)求
隨機(jī)閱讀
- 01-10使用C語(yǔ)言求解撲克牌的順子及n個(gè)骰子
- 04-02jquery與jsp,用jquery
- 08-05dedecms(織夢(mèng))副欄目數(shù)量限制代碼修改
- 08-05DEDE織夢(mèng)data目錄下的sessions文件夾有什
- 08-05織夢(mèng)dedecms什么時(shí)候用欄目交叉功能?
- 01-11Mac OSX 打開原生自帶讀寫NTFS功能(圖文
- 01-10C#中split用法實(shí)例總結(jié)
- 01-10SublimeText編譯C開發(fā)環(huán)境設(shè)置
- 01-11ajax實(shí)現(xiàn)頁(yè)面的局部加載
- 01-10delphi制作wav文件的方法