揹包問題(Knapsack problem)是一種組合優化的NP完全問題。問題可以描述爲:給定一組物品,每種物品都有自己的重量和價格,在限定的總重量內,我們如何選擇,才能使得物品的總價格最高。問題的名稱來源於如何選擇最合適的物品放置於給定揹包中。相似問題經常出現在商業、組合數學,計算複雜性理論、密碼學和應用數學等領域中。也可以將揹包問題描述爲決定性問題,即在總重量不超過W的前提下,總價值是否能達到V?它是在1978年由Merkle和Hellman提出的。
01揹包
問題描述:
給定n種物品和一揹包。物品i的重量是wi,其價值爲vi,揹包的容量爲C。問應如何選擇裝入揹包的物品,使得裝入揹包中物品的總價值最大?
算法分析:
二維做法
用一個數組f[i][j]表示,在只有i個物品,容量爲j的情況下揹包問題的最優解,那麼當物品種類變大爲i+1時,最優解是什麼?第i+1個物品可以選擇放進揹包或者不放進揹包(這也就是0和1),假設放進揹包(前提是放得下),那麼f[i+1][j]=f[i][j-w[i+1]+v[i+1];如果不放進揹包,那麼f[i+1][j]=f[i][j]。
這就得出了狀態轉移方程:
f[i+1][j]=max(f[i][j],f[i][j-w[i+1]+v[i+1])。
#include<cstdio>
#include<iostream>
#include<cmath>
#include<cstring>
#include<string>
#include<algorithm>
#define fre(x) freopen(#x".in","r",stdin),freopen(#x".out","w",stdout);
using namespace std;
const int MAX=2147483647;
const int N=2e2+10;
int f[40][N],w[40],v[40],n,C;
int main()
{
//fre();
scanf("%d%d",&C,&n);
for(int i=1;i<=n;i++) scanf("%d%d",&w[i],&v[i]);
for(int i=1;i<=n;i++)
for(int j=C;j>0;j--)
{
if(w[i]<=j) f[i][j]=max(f[i-1][j],f[i-1][j-w[i]]+v[i]);
else f[i][j]=f[i-1][j];
}
printf("%d",f[n][C]);
return 0;
}
一維做法:
#include<cstdio>
#include<iostream>
#include<cmath>
#include<cstring>
#include<string>
#include<algorithm>
#define fre(x) freopen(#x".in","r",stdin),freopen(#x".out","w",stdout);
using namespace std;
const int MAX=2147483647;
const int N=2e2+10;
int f[N],w[40],v[40],n,C;
int main()
{
//fre();
scanf("%d%d",&C,&n);
for(int i=1;i<=n;i++) scanf("%d%d",&w[i],&v[i]);
for(int i=1;i<=n;i++)
for(int j=C;j>=w[i];j--)
if(w[i]<=j) f[j]=max(f[j],f[j-w[i]]+v[i]);
printf("%d",f[C]);
return 0;
}
其他揹包問題:
揹包問題(2)-完全揹包