一:01背包
有 NN 件物品和一个容量是 VV 的背包。每件物品只能使用一次。
第 ii 件物品的体积是 vivi,价值是 wiwi。
求解将哪些物品装入背包,可使这些物品的总体积不超过背包容量,且总价值最大。
输出最大价值。
输入格式
第一行两个整数,N,VN,V,用空格隔开,分别表示物品数量和背包容积。
接下来有 NN 行,每行两个整数 vi,wivi,wi,用空格隔开,分别表示第 ii 件物品的体积和价值。
输出格式
输出一个整数,表示最大价值。
数据范围
0<N,V≤10000<N,V≤1000
0<vi,wi≤10000<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 }
二:完全背包
有 NN 种物品和一个容量是 VV 的背包,每种物品都有无限件可用。
第 ii 种物品的体积是 vivi,价值是 wiwi。
求解将哪些物品装入背包,可使这些物品的总体积不超过背包容量,且总价值最大。
输出最大价值。
输入格式
第一行两个整数,N,VN,V,用空格隔开,分别表示物品种数和背包容积。
接下来有 NN 行,每行两个整数 vi,wivi,wi,用空格隔开,分别表示第 ii 种物品的体积和价值。
输出格式
输出一个整数,表示最大价值。
数据范围
0<N,V≤10000<N,V≤1000
0<vi,wi≤10000<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 }
三:多重背包(未优化)
有 NN 种物品和一个容量是 VV 的背包。
第 ii 种物品最多有 sisi 件,每件体积是 vivi,价值是 wiwi。
求解将哪些物品装入背包,可使物品体积总和不超过背包容量,且价值总和最大。
输出最大价值。
输入格式
第一行两个整数,N,VN,V,用空格隔开,分别表示物品种数和背包容积。
接下来有 NN 行,每行三个整数 vi,wi,sivi,wi,si,用空格隔开,分别表示第 ii 种物品的体积、价值和数量。
输出格式
输出一个整数,表示最大价值。
数据范围
0<N,V≤1000<N,V≤100
0<vi,wi,si≤1000<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 }
五:分组背包:
有 NN 组物品和一个容量是 VV 的背包。
每组物品有若干个,同一组内的物品最多只能选一个。
每件物品的体积是 vijvij,价值是 wijwij,其中 ii 是组号,jj 是组内编号。
求解将哪些物品装入背包,可使物品总体积不超过背包容量,且总价值最大。
输出最大价值。
输入格式
第一行有两个整数 N,VN,V,用空格隔开,分别表示物品组数和背包容量。
接下来有 NN 组数据:
- 每组数据第一行有一个整数 SiSi,表示第 ii 个物品组的物品数量;
- 每组数据接下来有 SiSi 行,每行有两个整数 vij,wijvij,wij,用空格隔开,分别表示第 ii 个物品组的第 jj 个物品的体积和价值;
输出格式
输出一个整数,表示最大价值。
数据范围
0<N,V≤1000<N,V≤100
0<Si≤1000<Si≤100
0<vij,wij≤1000<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