有N件物品和一個容量爲V的揹包。(每種物品均只有一件)第i件物品的費用是c[i],價值是w[i]。求解將哪些物品裝入揹包可以使價值總和最大。
有N種物品和一個容量爲V的揹包,每種物品都有無限件可用。第i種物品的費用是c[i],價值是w[i]。求解將哪些物品裝入揹包可以使這些物品的費用總和不超過揹包容量,且價值總和最大。
有N種物品和一個容量爲V的揹包。第i種物品最多有n[i]件可用,每件費用是c[i],價值是w[i]。求解將哪些物品裝入揹包可以使這些物品的費用總和不超過揹包容量,且價值總和最大。
01揹包:max {f[ i-1 ][ v ], f[ i ][ v - vi ] + wi } 時間 O(VN) 空間 O(VN) -->O(V)node
for(i=1; i<=n; i++)ios
for(j=v; j>=v[ i ]; j-- )//逆序保持次循環內的值和上個循環內的值單次比較算法
f[i][v] = max {f[ i - 1 ][ v ], f[ i ][ v - vi ] + wi }優化
徹底揹包:max { f[ i-1 ][ v ], f[ i ][ v - c * vi ]+ c * wi } 時間 O(VN) 空間 O(V)spa
for(i=1; i<=n; i++)code
for(j=v[ i ]; j <= v; j++ )//順序保證同一個循環內的值相互比較blog
f[i][v] = max { f[ i-1 ][ v ], f[ i ][ v - c * vi ]+ c * wi }ip
多重揹包:max { f[ i-1 ][ v ], f[ i ][ v - ci * vi ]+ ci * wi | 0 <= ci * vi <= v}ci
時間 O(v*n*∑ci)it
for(i=1; i<= n; i++)
for(k=1; k <= ci; k--)
for(j=v; j >= vi; j--)
f[v] = max( f[v], f[v - vi] + wi );
時間 O(v*n*∑log ci)
if ( ci * vi > v ) completePack( vi, wi );
else {
int i=1;
while( i<ci )
{
zeroOnePack( i * vi, i * wi );
ci - = i;
i+=i;
}zeroOnePack( ci * vi , ci * wi );
}
01揹包 hdu 2602描述:
現有 n 件物品,一個最大容量爲 w 的揹包。第 i 件物品重量爲 wi ,價值爲 vi 。 已知對於一件物品,你必須選擇取或不取,且每件物品只能被取一次(這就是「0/1」的含義)。 求放置哪幾件物品進揹包,使得揹包中物品價值最大(或是求最大價值是多少等衍生問題)。
狀態轉化方程
f[i][V]= max {f[i-1][V-vi]+wi,f[i-1][V]}
優化算法 f[v]=max{f[V],f[V-vi]}
代碼以下:
// O1揹包。。 #include<iostream> using namespace std; #define MAX(a,b) ((a)>(b)?(a):(b)) struct node { int val,cap; }; node in [1000]; int re [1001]; int main() { int t,n,v,i,j,k; cin >> t; while(t--) { memset(re,0,sizeof(re)); cin >> n >> v; for (i=0; i<n; i++) cin >> in[i].val; for (i=0; i<n; i++) cin >> in[i].cap; for (i=0; i<n; i++) for (j=v ;j>=in[i].cap; j--) re[j]=MAX(re[j],re[j-in[i].cap]+in[i].val); //for(i=0; i<=v; i++)cout << re[i] <<" ";cout<< endl; cout << re[v] << endl; } return 0; }
徹底揹包 hdu 1114
#include<iostream> #include<climits> #define MIN(a,b) ((a)>(b)?(b):(a)) #include<cmath> using namespace std; int w[505],v[505],f[10000]; int main() { int t,bw,fw,n,i,j,k,ii; cin >> t; while(t--) { int len; cin >> bw >> fw >> n; len = fw-bw; for(i=1; i<=n; i++) cin >> w[i] >> v[i]; for(i=0; i<=len; i++) f[i]=0;//f[i]=1000000; //f[0]=0; for(i=1; i<=n; i++) for(j=v[i];j<=len;j++) //f[j]=MIN(f[j],f[j-v[i]]+w[i]); //for(ii=1; ii<=len; ii++)cout << f[ii]<<" ";cout << endl; if(j==v[i] || f[j-v[i]]>0) { if(f[j]==0)f[j]=f[j-v[i]]+w[i]; else f[j]=MIN(f[j],f[j-v[i]]+w[i]); } else continue; if(f[len]==0) //if(f[len]==1000000) cout << "This is impossible." << endl; else cout <<"The minimum amount of money in the piggy-bank is "<<f[len]<<"."<<endl; } return 0; }
多重揹包 hdu2191
#include<iostream> #define MAX(a,b) ((a)>(b)?(a):(b)) using namespace std; int V[101]; void zeroOnePack(int n, int tp, int th) { for(int i=n; i>=tp; i--) V[i]=MAX(V[i],V[i-tp]+th); } void completePack(int n, int tp, int th) { for(int i=tp; i<=n; i++) V[i]=MAX(V[i],V[i-tp]+th); } void multiPack(int n, int tp, int th, int tc) { if( tp*tc > n ) completePack(n,tp,th); else { int i=1; while(i<tc) { zeroOnePack(n,tp*i,th*i); tc-=i; i+=i; }zeroOnePack(n,tp*tc,th*tc); } } int main() { int p[101],h[101],c[101]; int t,n,m; cin >> t; while(t--) { int i,j,k; cin >> n >> m; for (i=1; i<=m; i++) cin >> p[i] >> h[i] >> c[i]; for(i=0; i<=n; i++)V[i]=0; for(i=1; i<=m; i++) multiPack(n,p[i],h[i],c[i]); //for(i=1; i<=n;i++)cout << V[i]<<" ";cout << endl; cout << V[n] << endl; } return 0; }