(蒟蒻的總結並不能表明什麼,只能說給之後的本身,防止後來忘記吧??可能有不對的地方,請指出)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
顯然咱們要取這兩種中最大的一種:利用函數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-