背包问题整理 一:01背包 二:完全背包 三:多重背包(未优化) 四:多重背包(二进制优化) 五:分组背包:
有 V 的背包。每件物品只能使用一次。
第 wi。
求解将哪些物品装入背包,可使这些物品的总体积不超过背包容量,且总价值最大。
输出最大价值。
输入格式
第一行两个整数,N,V,用空格隔开,分别表示物品数量和背包容积。
接下来有 i 件物品的体积和价值。
输出格式
输出一个整数,表示最大价值。
数据范围
0<vi,wi≤1000
输入样例
4 5
1 2
2 4
3 4
4 5
输出样例:
8
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 const int N = 1010; 5 6 int a[N], b[N]; 7 //int dp[N]; 8 int n, v; 9 10 vector<vector<int>> memo(N, vector<int>(N, -1)); 11 12 int dfs(int i, int j){ 13 if(memo[i][j] != -1) return memo[i][j]; 14 if(i == 0) return memo[i][j] = 0; 15 int dfs1 = dfs(i-1, j); 16 int dfs2 = -1; 17 if(j >= a[i]) dfs2 = dfs(i-1, j - a[i]) + b[i]; 18 return memo[i][j] = max(dfs1, dfs2); 19 } 20 21 int main(){ 22 cin >> n >> v; 23 for(int i = 1;i <= n;++i) cin >> a[i] >> b[i];//v p 24 /* 25 for(int i = 1;i <= n;++i) 26 for(int j = v;j >= a[i];--j) 27 dp[j] = max(dp[j], dp[j-a[i]] + b[i]);//核心,第i层状态由第i-1层状态得到 28 */ 29 cout << dfs(n, v) << endl; 30 return 0; 31 }
二:完全背包
有 V 的背包,每种物品都有无限件可用。
第 wi。
求解将哪些物品装入背包,可使这些物品的总体积不超过背包容量,且总价值最大。
输出最大价值。
输入格式
第一行两个整数,N,V,用空格隔开,分别表示物品种数和背包容积。
接下来有 i 种物品的体积和价值。
输出格式
输出一个整数,表示最大价值。
数据范围
0<vi,wi≤1000
输入样例
4 5
1 2
2 4
3 4
4 5
输出样例:
10
1 #include <iostream> 2 using namespace std; 3 4 const int N = 1010; 5 6 int dp[N]; 7 int n, v; 8 9 int w[N], p[N]; 10 11 int main(){ 12 cin >> n >> v; 13 for(int i = 1;i <= n;++i) cin >> w[i] >> p[i]; 14 15 for(int i = 1;i <= n;++i) 16 for(int j = w[i];j <= v;++j) 17 //max后的dp[j]表示的是第i-1层的值,dp[j-w[i]]表示的是当前第i层如果要选k个物品由选k-1个物品更新得到 18 dp[j] = max(dp[j], dp[j-w[i]] + p[i]); 19 cout << dp[v] << endl; 20 return 0; 21 }
三:多重背包(未优化)
有 V 的背包。
第 wi。
求解将哪些物品装入背包,可使物品体积总和不超过背包容量,且价值总和最大。
输出最大价值。
输入格式
第一行两个整数,N,V,用空格隔开,分别表示物品种数和背包容积。
接下来有 i 种物品的体积、价值和数量。
输出格式
输出一个整数,表示最大价值。
数据范围
0<vi,wi,si≤100
输入样例
4 5
1 2 3
2 4 1
3 4 3
4 5 2
输出样例:
10
1 #include <iostream> 2 using namespace std; 3 4 const int N = 1010; 5 6 int dp[N]; 7 int n, v; 8 9 int w[N], p[N], s[N]; 10 11 int main(){ 12 cin >> n >> v; 13 for(int i = 1;i <= n;++i) cin >> w[i] >> p[i] >> s[i]; 14 15 for(int i = 1;i <= n;++i){ 16 for(int j = v;j >= 0;--j){ 17 int t = 0; 18 while(t <= s[i] && j >= t * w[i]){ 19 dp[j] = max(dp[j], dp[j - t*w[i]] + t*p[i]); 20 ++t; 21 } 22 } 23 } 24 25 cout << dp[v] << endl; 26 return 0; 27 }
四:多重背包(二进制优化)
1 #include <iostream> 2 using namespace std; 3 4 const int N = 1000*2000; 5 6 int n, v; 7 int dp[N], w[N], p[N]; 8 9 int main(){ 10 cin >> n >> v; 11 //拆分 12 int cnt = 0; 13 for(int i = 1;i <= n;++i){ 14 int a, b, sum; cin >> a >> b >> sum; 15 int k = 1; 16 while(k <= sum){ 17 ++cnt; 18 w[cnt] = a*k; 19 p[cnt] = b*k; 20 sum -= k; 21 k *= 2; 22 } 23 if(sum){ 24 ++cnt; 25 w[cnt] = a*sum; 26 p[cnt] = b*sum; 27 } 28 } 29 //按照01背包问题求解 30 for(int i = 1;i <= cnt;++i) 31 for(int j = v;j >= w[i];--j) 32 dp[j] = max(dp[j], dp[j-w[i]]+p[i]); 33 34 cout << dp[v] << endl; 35 return 0; 36 }
五:分组背包:
有 V 的背包。
每组物品有若干个,同一组内的物品最多只能选一个。
每件物品的体积是 j 是组内编号。
求解将哪些物品装入背包,可使物品总体积不超过背包容量,且总价值最大。
输出最大价值。
输入格式
第一行有两个整数 N,V,用空格隔开,分别表示物品组数和背包容量。
接下来有 N 组数据:
- 每组数据第一行有一个整数 i 个物品组的物品数量;
- 每组数据接下来有 j 个物品的体积和价值;
输出格式
输出一个整数,表示最大价值。
数据范围
0<vij,wij≤100
输入样例
3 5
2
1 2
2 4
1
3 4
1
4 5
输出样例:
8
1 #include <iostream> 2 using namespace std; 3 4 const int N = 110; 5 int v[N][N], w[N][N]; 6 int s[N]; 7 int dp[N]; 8 9 int main(){ 10 int n, m; cin >> n >> m; 11 for(int i = 1;i <= n;++i){ 12 cin >> s[i]; 13 for(int j = 1;j <= s[i];++j) 14 cin >> v[i][j] >> w[i][j]; 15 } 16 17 for(int i = 1;i <= n;++i) 18 for(int j = m;j >= 0;--j) 19 for(int k = 1;k <= s[i];++k) 20 if(j >= v[i][k]) 21 dp[j] = max(dp[j], dp[j - v[i][k]] + w[i][k]); 22 23 cout << dp[m] << endl; 24 return 0; 25 }
end