【總結】01揹包問題

(蒟蒻的總結並不能表明什麼,只能說給之後的本身,防止後來忘記吧??可能有不對的地方,請指出)ios

沒有算法標籤算法

在學習OI好幾個月後回來再看這個總結,發現本來寫的二維的是錯的,特此更正2019.6.18(開心的金明二維的痛)數組


讓咱們先附上一個01揹包問題的基本題目:函數

給定 n 種物品和一個容量爲 C 的揹包,物品 i 的重量是 wi,其價值爲 vi 。學習

問:應該如何選擇裝入揹包的物品,使得裝入揹包中的物品的總價值最大?優化

首先先是頭文件們以及定義們(還有輸入)spa

#inlcude<iostream>
#include<cstdio>
#include<algorithm>
#include<string>
#include<cstring>
#incude<camth>//把我所記住的頭文件全寫上了(你們不要學我); 
using namespace std;
int n,c;//定義物品數量及揹包容量; 
int w[1000],v[1000];//定義數組w[i]和v[i]分別表示物品i的質量和價值(1000毫無心義)
int f[1000][1000];//定義數組f[i][j]存放第i個時的當前最大值(亂說胡話)
int main()
{
    cin>>n>>c;//輸入n,c; 
    for(int i=1;i<=n;i++)
    cin>>w[i]>>v[i];//輸入第1~n個物體的質量和價值 ; 
    

接下來是時候發揮數組f的做用了。數組f存的是搜索(不是搜索)第i個物品時的最大價值。利用雙層循環,設數組f[i][j]爲第i個物品時剛好質量爲j(這裏有一點貪心???)的最大值,顯然到f[i][j]時有兩種可能:code

  1. 不選取第i個物品,則此時最大值爲f[i-1][j];
  2. 選取第i個物品,則此時的最大值是f[i-1][j-w[i]]+v[i];(這裏有必要解釋一下:由於選取第i個物品後剛好裝滿j的容積,那麼在沒選取第i個物品時,剛好裝滿的是j-w[i]的容積。那麼選取第i個物品以前的最大值就爲f[i-1][j-w[i]],這時再加上第i個物品的價值,獲得結果。

顯然咱們要取這兩種中最大的一種:利用函數max,則有:blog

for(int i=1;i<=n;i++)
        for(int j=c;j>=0;j--)
        if(j-w[i]>=0)f[i][j]=max(f[i-1][j],f[i-1][j-w[i]]+v[i]);
else f[i][j]=f[i-1][j];

當循環結束時,咱們就求得了最大總價值f[n][c];ci

這裏附上表幫助理解:

 

 附上完整代碼:

#inlcude<iostream>
#include<cstdio>
#include<algorithm>
#include<string>
#include<cstring>
#incude<camth>//把我所記住的頭文件全寫上了(你們不要學我); 
using namespace std;
int n,c;//定義物品數量及揹包容量; 
int w[1000],v[1000];//定義數組w[i]和v[i]分別表示物品i的質量和價值(1000毫無心義); 
int f[1000][1000];//定義數組f[i][j]存放第i個時的當前最大值(亂說胡話); 
int main()
{
    cin>>n>>c;//輸入n,c; 
    for(int i=1;i<=n;i++)
    cin>>w[i]>>v[i];//輸入第1~n個物體的質量和價值 ; 
    for(int i=1;i<=n;i++)
        for(int j=c;j>=0;j--){//從c開始倒敘搜索並j>=w[i]是爲了防止出現負下標
        if(j-w[i]>=0)f[i][j]=max(f[i-1][j],f[i-1][j-w[i]]+v[i]);
else f[i][j]=f[i-1][j]; cout
<<f[n][c]<<endl;

顯然數組會很佔空間,因此咱們優化爲一維數組(儘管沒太聽懂):

 

#inlcude<iostream>
#include<cstdio>
#include<algorithm>
#include<string>
#include<cstring>
#incude<camth>//把我所記住的頭文件全寫上了(你們不要學我); 
using namespace std;
int n,c;//定義物品數量及揹包容量; 
int w[1000],v[1000];//定義數組w[i]和v[i]分別表示物品i的質量和價值(1000毫無心義); 
int f[1000];//定義數組f[i][j]存放第i個時的當前最大值(亂說胡話); 
int main()
{
    cin>>n>>c;//輸入n,c; 
    for(int i=1;i<=n;i++)
    cin>>w[i]>>v[i];//輸入第1~n個物體的質量和價值 ; 
    for(int i=1;i<=n;i++)
        for(int j=c;j>=w[i];j--)
        f[j]=max(f[j],f[j-w[i]]+v[i]);
    cout<<f[c]<<endl;//但願沒輸錯……

end-

相關文章
相關標籤/搜索