本文最后更新于 2025年3月1日 上午
完全背包
题目:
有 N 种物品和一个容量是 V 的背包。
第 i 种物品最多有 si 件,每件体积是 vi,价值是 wi。
求解将哪些物品装入背包,可使物品体积总和不超过背包容量,且价值总和最大。
输出最大价值。
输入格式
第一行两个整数,N,V,用空格隔开,分别表示物品种数和背包容积。
接下来有 N 行,每行三个整数 vi,wi,si,用空格隔开,分别表示第 i 种物品的体积、价值和数量。
输出格式
输出一个整数,表示最大价值。
数据范围
0<N≤1000
0<V≤2000
0<vi,wi,si≤2000
提示:
本题考查多重背包的二进制优化方法。
输入样例
1 2 3 4 5
| 4 5 1 2 3 2 4 1 3 4 3 4 5 2
|
输出样例:
暴力解法:
暴力动态规划(只能解决N较小的情况):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| #include<bits/stdc++.h> using namespace std;
const int N=110; int w,v,s; int n,m; int dp;
int main() { ios::sync_with_stdio(false); cin.tie(nullptr); cin>>n>>m; for(int i=1;i<=n;i++) { cin>>v>>w>>s; for(int j=0;j<=m;j++) { for(int k=0;k<=s&&k*v<=j;k++) { dp=max(dp,dp+w*k); } } } cout<<dp; return 0; }
|
二进制优化:
使用二进制优化将背包降至一维,利用倍增思想,将背包数量用二进制表示,如1+2+4+8+······,可以组成1~n之间的所有数,这样就将背包降至一维,将多重背包问题转换成01背包问题;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
| #include<bits/stdc++.h> using namespace std;
const int N=12010,M=2010; int v[N],w[N]; int dp[M]; int n,m;
int main() { ios::sync_with_stdio(false); cin.tie(nullptr); cin>>n>>m; int cnt=0; for(int i=1;i<=n;i++) { int a,b,s; cin>>a>>b>>s; int k=1; while(k<s) { cnt++; v[cnt]=a*k; w[cnt]=b*k; s-=k; k*=2; } if(s>0) { cnt++; v[cnt]=a*s; w[cnt]=b*s; } } n=cnt; for(int i=1;i<=n;i++) { for(int j=m;j>=v[i];j--) { dp[j]=max(dp[j],dp[j-v[i]]+w[i]); } } cout<<dp[m]; return 0; }
|