咋先不說解決這種揹包問題的方法,個人感覺應該先把產生問題的背景描述出來會比較好一點,如下:
1,問題描述
有n件物品和乙個容量為v的揹包。第i件物品的重量是c[i],價值是w[i]。求解將哪些物品裝入揹包可使這些物品的重量總和不超過揹包容量,且價值總和最大。,
2,具體例項:
現有乙個容量為10kg的揹包,還有5件不同質量和**的物品,現在讓你,把這些物品有選擇性的放到揹包裡面,使得揹包的價值最大且揹包裡物品的重量不能超過揹包的最大容量。5件物品的重量分別為與之對應的質量分別為對應的**為。
問題特點:
每種物品僅有一件,可以選擇放或不放。
解決問題思路:
我把揹包容量從0列舉到10,因為揹包容量太大,所以求解很複雜。故此,我就分別求,看揹包容量分別為0,1,2,3....10時,怎樣放物品能使不同容量的揹包價值最大。放物品的時候也是乙個乙個的放,至於是否放得進去,看如下例子:
(想了好久也不知道該怎麼敘述,這裡我就直接舉例說明,看我**能不能看懂,要是他能看懂的話我,相信你們就能看懂)
現在,我準備把物品a往揹包裡面放,容易看出,揹包容量為0和1時,物品a是放不進去的,所以價值為0,當揹包容量為2,3,4....10時可以放進去,且與之對應的價值都是6,這應該好理解吧,就是說,揹包容量為2時,把a放進去,揹包滿了,價值為6,容量為3時,a放進去時,揹包沒滿,但價值還是6,以此類推後面的容量對應的價值都是6。如圖,
現在,在以上操作的基礎上(物品a放入相應容量的揹包中使得揹包的價值最大)再把物品b放入相應容量的揹包中,由於b的重量為也是2,所以揹包容量為0和1時不能放b,所以對應的價值,應該是上一次(放入a)時的最大價值,結果還是0,然後容量為2時,做出判斷,如果放入b,揹包滿了不能放a了,價值是3,如果不放b,那麼價值就是a的價值6,很顯然6大於3 所以這兒應該放a,然後一直往後放,容量為4時,可以把a和b都放進去,價值為9,以後容量為5,6,7,8,9,10價值都是9 如下圖
好了,現在可以把c也放進去了如圖
最後把d和e也放進去
至此,所有的物品都已有選擇性的放進去了,但是你還不知道到底哪個是真的放進去了,哪個沒放進
不過,最大值可以看出來,就是15
找出最優解:
判斷放進去的物品:
我們從最大值開始判斷,揹包容量為10時,(有選擇性的放或不放e後)價值最大為15,(有選擇性的放d或不放d後)價值最大為14,這就說明了乙個問題,要是沒有放e,那麼最大價值應該是14,所以確定e肯定放進去了。
然後判斷d是否放入了揹包,判斷d時,先把e的重量減掉(因為e已經確定放進去了,所以接下來判斷的就是剩餘揹包容量中是否放入了d),10-4=6,看揹包容量為6時的情況,有圖可以看出,對d沒有進行任何操作時的價值為9(看c行,容量為6的那個價值),然後對d進行 」有選擇性的放或不放「 的操作後,價值還是9,那說明d肯定沒放,
對c判斷,同樣的,先算出剩餘揹包容量,由於已近確定放e,沒放d,所以剩餘揹包容量為10-4=6,有圖可知,
對c沒有進行任何操作時的價值為9(看b行,容量為6的那個價值),然後對c進行 」有選擇性的放或不放「 的操作後,價值還是9,那說明c肯定沒放,
對b判斷,以上可知,c,d都沒放,放入了e,揹包剩餘容量還是6,對b
沒有進行任何操作時的價值為6(看a行,容量為6的那個價值),然後對b進行 」有選擇性的放或不放「 的操作後,價值是9,那說明c肯定放進去了,
對a判斷,以上可知剩餘揹包容量為10-4-2=4,對a
沒有進行任何操作時的價值為0(啥都不操作的時候),然後對a進行 」有選擇性的放或不放「 的操作後,價值是6,那說明a肯定放進去了,
至此我們可以得出我們的最優解揹包裡放進去的物品分別是a,b,e,還可以知道,揹包容量為2+2+4=8時,揹包的價值就已經達到最大了。
下面附上**
#include#include#includeusing namespace std;
const int c = 10; //揹包的容量
const int w = ;//物品的重量,其中0號位置不使用 。
const int v = ;//物品對應的待加,0號位置置為空。
const int n = sizeof(w)/sizeof(w[0]) - 1 ; //n為物品的個數
int x[n+1];
void package0_1(int m[11],const int w,const int v,const int n)//n代表物品的個數 用於進行「有選擇性放或不放物品」 的操作
} }} void answer(int m[11],const int n) //選出最優解,判斷那個放入了揹包,那個沒有放,
} int main()
answer(m,n);
printf("the best answer is:\n");
for( i = 1; i <= 5; i++)
printf("%d ",x[i]);
system("pause");
return 0;
}
m[i][j] = m[i-1][j] > m[i-1][j-w[i]] + v[i]?
m[i-1][j] : m[i-1][j-w[i]] + v[i];
深度分析上述表示式
對於該式子的理解,首先得清楚一點就是每個物品只有兩種狀態 放或不放 例如那物品a和b來說,相互組合之後有三種情況
(1)放a不放b (2)放b不放a (3)即放a又放b
其中怎麼判斷到底選擇哪種放發 主要就看上面這個公式,看左面,其中m [i-1] [j]表示的就是放a不放b時的揹包的價值 m[i-1][j-w[i]]+v[i]這個式子有兩層意思:只放b a與b都放,具體的實現就要看是否滿足對應的條件了,這裡面,給我的感覺是,它直接假設把第i(這裡是物品b)個物品放進去,下面我給你分析一下:
放b後(第i個物品),那麼揹包剩餘的質量就是j-w[i],然後看前i-1(在這裡只有物品a)個物品在剩餘的揹包質量中的價值是多少,即m[i-1][j-w[i]]。最後加上物品第i個(這裡是物品b)物品的價值v[i],最終的公式是m[i-1][j-w[i]]+v[i]
j=2,3時
具體的例子是,現在開始放b,即判斷m[2][j](j的範圍是0到10)的值,我們乙個乙個的判斷,因為b的質量為2,所以只有揹包的質量等於2 時才開始進行方與不放的操作,那麼現在使m[2][2]等於m[1][2]還是m[1][0]+v[1] 這裡面m[1][2]的意思就是放a不放b ,那麼價值就是a的價值=6,然後看m[1][0]+v[1]這裡我前面說了,直接假設把b放進去,那麼揹包剩餘質量為j-w[i]=0,由此可知前i-1個物品(在這裡只有a)是放不進去的,那麼價值為0,然後加上第i個物品的價值v[i]=3,所以最終的價值m[i-1][j-w[i]]+v[i]=3其中表達的意思是放b不放a,最終判斷m[1][2]=6大於m[1][0]+v[1]=3所以m[2][2]=6,後面的j=3,判斷方法於此一樣
j=4,5,6,7,8,9,10時
這裡,再說一下j=4時的情況,現在使m[2][4]等於m[1][4]還是m[1][2]+v[4] 這裡面m[1][4]的意思就是放a不放b ,那麼價值就是a的價值=6,然後看m[1][2]+v[4]這裡我前面說了,直接假設把b放進去,那麼揹包剩餘質量為j-w[i]=2,由此可知前i-1個物品(在這裡只有a)是可以放進去的,那麼價值為6,然後加上第i個物品的價值v[4]=3,所以最終的價值m[i-1][j-w[i]]+v[i]=9其中表達的意思是a和b都放進去,最終判斷m[1][4]=6小於m[1][2]+v[4]=9所以m[2][4]=9.後面的j=5,6,7,8,9,10 的判斷方法於此一樣
揹包問題 01揹包問題
n個物品,總體積是v,每個物品的體積的vi,每個物品的最大價值是wi,在不超過v的體積下求最大價值 eg揹包容積為 5 物品數量為 4 物品的體積分別為 物品的價值分別為 思路定義乙個二位陣列int f new int n 1 v 1 f i j 就表示在1 i個物品中選取體積小於v的情況的最大價值...
揹包問題 01揹包
有n件物品和乙個容量為v的揹包。第i件物品的重量是c i 價值是w i 求解將哪些物品裝入揹包可使價值總和最大。01揹包中的 01 就是一種物品只有1件,你可以選擇放進去揹包即1,也可以選擇不放入揹包中即0。include include using namespace std const int ...
揹包問題(01揹包)
1085 揹包問題 在n件物品取出若干件放在容量為w的揹包裡,每件物品的體積為w1,w2 wn wi為整數 與之相對應的價值為p1,p2 pn pi為整數 求揹包能夠容納的最大價值。input 第1行,2個整數,n和w中間用空格隔開。n為物品的數量,w為揹包的容量。1 n 100,1 w 10000...