背包问题模板
1. 01背包问题
有 N 件物品和一个容量是 V 的背包。每件物品只能使用一次。第 i 件物品的体积是 vi,价值是 wi。求解将哪些物品装入背包,可使这些物品的总体积不超过背包容量,且总价值最大。输出最大价值。
1 #include <iostream> 2 #include <cstring> 3 #include <algorithm> 4 using namespace std; 5 const int maxn = 1010; 6 int n, m; 7 int dp[maxn]; 8 int main(){ 9 cin >> n >> m; 10 for(int i = 1; i <= n; i++){ 11 int v, w; 12 cin >> v >> w; 13 for(int j = m; j >= v; j--)//体积从大到小枚举 14 dp[j] = max(dp[j], dp[j - v] + w); 15 } 16 cout << dp[m] << endl; 17 return 0; 18 }
2. 完全背包问题
有 N 件物品和一个容量是 V 的背包。每件物品可以使用无限次。第 i 件物品的体积是 vi,价值是 wi。求解将哪些物品装入背包,可使这些物品的总体积不超过背包容量,且总价值最大。输出最大价值。
1 #include <iostream> 2 #include <cstring> 3 #include <algorithm> 4 using namespace std; 5 const int maxn = 1010; 6 int n, m; 7 int dp[maxn]; 8 int main(){ 9 cin >> n >> m; 10 for(int i = 1; i <= n; i++){ 11 int v, w; 12 cin >> v >> w; 13 for(int j = v; j <= m; j++)//体积从小到大枚举 14 dp[j] = max(dp[j], dp[j - v] + w); 15 } 16 cout << dp[m] << endl; 17 return 0; 18 }
3. 多重背包问题
有 N 件物品和一个容量是 V 的背包。第 i 种物品最多有 si 件,每件体积是 vi,价值是 wi。求解将哪些物品装入背包,可使这些物品的总体积不超过背包容量,且总价值最大。输出最大价值。
1 #include <bits/stdc++.h> 2 using namespace std; 3 int w[1000]; 4 int v[1000]; 5 int m[1000]; 6 int dp[1000]; 7 int main(){ 8 int a,W,n; 9 cin>>a; 10 while(a--){ 11 memset(dp,0,sizeof(dp)); 12 cin>>W>>n; 13 for(int i=0;i<n;i++){ 14 cin>>w[i]>>v[i]>>m[i]; 15 } 16 for (int i=0;i<n;i ++){ 17 int num =m[i]; 18 for (int k=1; num >0;k<<=1){ 19 int mul =min (k,num ); 20 for (int j=W;j >=w[i]* mul;j --){ 21 dp[j]= max (dp[j],dp[j-w[i]* mul ]+v[i]* mul ); 22 } 23 num -= mul; 24 } 25 } 26 cout<<dp[W]<<endl; 27 } 28 return 0; 29 }
单调队列优化:
1 #include<bits/stdc++.h> 2 using namespace std; 3 int n,m,l,r; 4 const int N=1e5+7; 5 int dp[N],q[N],num[N]; 6 7 int main(){ 8 int v,w,c; 9 scanf("%d%d",&n,&m); 10 for(int i=1;i<=n;i++){ 11 scanf("%d%d%d",&v,&w,&c); //v 体积 w 价值 c 数量 12 if(c>m/v) c=m/v; 13 for(int j=0;j<v;j++){ 14 l=r=1; 15 for(int k=0;k<=(m-j)/v;k++){ 16 int tmp=dp[k*v+j]-k*w; 17 while(l<r&&q[r-1]<=tmp) r--; 18 q[r]=tmp; 19 num[r++]=k; 20 while(l<r&&k-num[l]>c) l++; 21 dp[k*v+j]=max(dp[k*v+j],q[l]+k*w); 22 } 23 } 24 } 25 printf("%d\n",dp[m]); 26 27 return 0; 28 }