01背包(修订版)
由于時(shí)間比較充裕,重新修訂一部分。
這次把一些補(bǔ)充的放進(jìn)來,其他的基礎(chǔ)說明見后半部分
這些一共說明:01背包、完全背包、多重背包 ?將會(huì)詳細(xì)說明。
三種背包混合、二維背包、分組背包、依賴背包、泛化背包 將大致說明。
?
01背包
如上次說明一般,這次提一下優(yōu)化和其他說明
首先我做01背包的思路的是在背包價(jià)值固定的情況下,不斷遍歷增加物品,獲取當(dāng)前背包容量下課存放的最大價(jià)值
同時(shí)也有另一種做法:物品固定,遍歷背包大小,獲取該物品存放與否對(duì)總價(jià)值的影響。
后一種肯能優(yōu)化更高一點(diǎn) 但不會(huì)太多,兩者復(fù)雜度都是O(VN)
其中時(shí)間復(fù)雜度無法優(yōu)化,但空間復(fù)雜度可以進(jìn)行簡(jiǎn)單優(yōu)化到O(N)
因?yàn)閯?chuàng)建二維數(shù)組的目的是為了記錄中間變量,每次記錄當(dāng)前行的值,下一次循環(huán)的時(shí)候與上一次的值進(jìn)行比較。
那么就可以優(yōu)化為以為一維數(shù)組,數(shù)組記錄當(dāng)前行的值,下一次循環(huán)的時(shí)候倒序判斷,因?yàn)槊看闻袛嗟闹凳巧弦恍袑?duì)應(yīng)的值和上一行列數(shù)靠前的值加上物品的價(jià)值。
倒序遍歷的時(shí)候可以把值進(jìn)行覆蓋更新,以便以后多次更新利用。
下面放上代碼吧:
1 For(int i= 0, i<N; i++ ){ 2 for(int j = U; j>Ti; j--}{ 3 F[j] = Max(F[j], f[j-Ti]+Vi) 4 } 5 }同樣的需要進(jìn)行初始化賦值。
這里提一下,之前以為賦值為0就好了,后來發(fā)現(xiàn)在大神們的思想里又對(duì)問題進(jìn)行了細(xì)分
包括1.只求出最大價(jià)值,不要求必須袋子放滿 ?2.恰好裝滿背包時(shí)最大價(jià)值
是不是感受到大神們滿滿的惡意
下面用原話來進(jìn)行解釋(我怕我解釋不清楚)
我們看到的求最優(yōu)解的背包問題題目中,事實(shí)上有兩種不太相同的問法。有的題目
要求“恰好裝滿背包”時(shí)的最優(yōu)解,有的題目則并沒有要求必須把背包裝滿。一種區(qū)別
這兩種問法的實(shí)現(xiàn)方法是在初始化的時(shí)候有所不同。
如果是第一種問法,要求恰好裝滿背包,那么在初始化時(shí)除了F[0] 為0,其它
F[1::V ] 均設(shè)為?1,這樣就可以保證最終得到的F[V ] 是一種恰好裝滿背包的最優(yōu)解。
如果并沒有要求必須把背包裝滿,而是只希望價(jià)格盡量大,初始化時(shí)應(yīng)該將F[0::V ]
全部設(shè)為0。
這是為什么呢?可以這樣理解:初始化的F 數(shù)組事實(shí)上就是在沒有任何物品可以放
入背包時(shí)的合法狀態(tài)。如果要求背包恰好裝滿,那么此時(shí)只有容量為0 的背包可以在什
么也不裝且價(jià)值為0 的情況下被“恰好裝滿”,其它容量的背包均沒有合法的解,屬于
未定義的狀態(tài),應(yīng)該被賦值為-∞ 了。如果背包并非必須被裝滿,那么任何容量的背包
都有一個(gè)合法解“什么都不裝”,這個(gè)解的價(jià)值為0,所以初始時(shí)狀態(tài)的值也就全部為0
了。
?
完全背包
下面說一下完全背包,完全背包就是說物品的個(gè)數(shù)無限個(gè),可以重復(fù)放置
這樣就要求比較的時(shí)候不能與上一個(gè)相比,于是狀態(tài)轉(zhuǎn)移方程式就改為與當(dāng)前行進(jìn)行比較
valueData[i][j] = Max(valueData[i-1][j], valueData[i][j-weight[z]]+value[z]);與01背包的區(qū)別是
因?yàn)槲锲反娣艧o個(gè)數(shù)限制,完全可以多次放置,所以比較對(duì)象是當(dāng)前物品放置歷史最優(yōu)值和不放置當(dāng)前物品。
如此則完成完全背包的實(shí)現(xiàn)。
同樣的 ?完全背包也可以進(jìn)行空間復(fù)雜度的優(yōu)化,原理與01背包相同。
?
多重背包
?多重背包的定義是物品個(gè)數(shù)有限個(gè),并且說明當(dāng)前物品個(gè)數(shù)。
狀態(tài)轉(zhuǎn)移方程式
1 valueData[i][j] = Max ( valueData[i-1][j - k*weight[i]] +k*value[i] ) 0<=k<=num[i]解釋起來就是物品放置個(gè)數(shù)內(nèi)求出最大價(jià)值
?
?
?混合三種背包
字面意思,三種背包都存在的混合體,有的物品只有一個(gè)(01背包),有的物品無限多個(gè)(完全背包)
有的物品有限多個(gè)(多重背包),這是可以將問題劃為三分,分別把之前的背包封裝起來,判斷物品是哪一類分別調(diào)用不同的方法
最終求得最優(yōu)解
二維背包
物品的屬性有兩個(gè),要同時(shí)滿足才可放進(jìn)去,例如袋子存放物品既要考慮物品體積也要考慮物品重量
對(duì)應(yīng)解決辦法是創(chuàng)建的數(shù)組也增加維度,
詳細(xì)的。。。。。不會(huì)
分組背包
意思多個(gè)物品被分組,且分組內(nèi)物品相互排斥,只能取出一個(gè)
詳細(xì)。。。。。不會(huì)
泛化背包
意思是物品沒有固定價(jià)值和質(zhì)量,物品的價(jià)值和質(zhì)量隨著分配的空間變化 ,。。。。。。不會(huì)
感覺就像液體水一樣,好幾種水,每個(gè)都是泛化對(duì)象,但又感覺不會(huì)這么簡(jiǎn)單。。。是在搞不懂大神們是怎么思考問題的
? OVER
背包問題說起來就是不斷的在基礎(chǔ)上提出新的問題,再不斷解決、不斷提問題
然后大神們津津樂道,我卻瘋掉了。。
?
?
以下是上次分享的內(nèi)容
第一次分享,并不知道該拿出些什么,之前學(xué)的算法好像都還回去了。
最后祭出了背包,可是背包九講又不全會(huì),于是拿出了最簡(jiǎn)單的01背包。
話說。。。。01背包也忘了
開始復(fù)習(xí)ing。
?
1.01背包
首先01背包是對(duì)一個(gè)有固定容積的“”盒子“”進(jìn)行物品存放,有N個(gè)物品,
每個(gè)物品的價(jià)值、體積分別是V1/T1、V2/T2、、、Vn/Tn。
需要求出能存放的最大價(jià)值。
按照固有思想,肯定放置性價(jià)比最高的,但是存在容積不匹配的情況
隨便一個(gè)反例,有一個(gè)價(jià)值10、體積5和一個(gè)價(jià)值1體積1的物品,放在容量為4的袋子中。
如果選擇倒推,則變成了暴力搜索了,時(shí)間復(fù)雜度就變大了。
?
在此基礎(chǔ)上,機(jī)智的前輩們用貪心思想,加上動(dòng)態(tài)規(guī)劃完成了01背包。
將一個(gè)大問題的最優(yōu)解,分解成一堆堆小問題的最優(yōu)解,
要求得能放置的最大價(jià)值,對(duì)于每個(gè)物品求出放與不放的最優(yōu)解。
例如對(duì)第i個(gè)物品,在能夠放置的前提下,求出放這個(gè)物品和不放這個(gè)物品的最優(yōu)值。
得到狀態(tài)轉(zhuǎn)移方程式:
F[i][j] = Max(F[i-1][j], F[i-1][j-Ti]+Vi);
舉例說明:
兩個(gè)0的初始化是為了放置數(shù)組越界出現(xiàn)異常。
完全背包、多重背包的拓展
完全背包:在01背包的基礎(chǔ)上,每個(gè)物品可以無限制存放個(gè)數(shù)。
狀態(tài)轉(zhuǎn)移方程式改成與F[i][j-Ti]+Vi。
多重背包:在01背包基礎(chǔ)上,每個(gè)物品可以放置有限次數(shù)且不固定。
01背包中存在價(jià)值體積相同的物品,可以轉(zhuǎn)化為01背包思考。
剩下的幾種,不會(huì)。。。。
轉(zhuǎn)載于:https://www.cnblogs.com/yishilin/p/8397737.html
總結(jié)
- 上一篇: fastJson去掉指定字段
- 下一篇: Django知识总结(一)