PART1(算法思想简介)
1.实现:
2.时间复杂度:
3.特别优势:
4.适用情况:
5.需要注意的点:
6:函数、变量名的解释+英文:
- volume(体积)
- quantity(数量)
PART2(算法各种类型(并附上代码))
TYPE1 01背包:
普通解法:O(VN)【空间也是O(VN)】从1~n件物品,对已经用了j的空间的情况下尝试放入(其实可能没有用到这么多的空间,但这样的答案肯定更新不了最优解【大的空间放的东西肯定比小的空间多】,所以没关系啦),放得下的就放进去看能不能更新最优解。
#include <iostream> #include <cstring> using namespace std; const int N = 21; const int V = 1e3+10; int bagDp[N][V]; int value[N], volume[N]; int main() { int n, v; cin >> n >> v; for(int i = 1;i <= n;i++){ cin >> value[i] >> volume[i]; } for(int i = 1;i <= n;i++){ for(int j = 0;j <= v;j++){ if(j >= volume[i]){//提前判断装不装得下 bagDp[i][j] = max(bagDp[i - 1][j - volume[i]] + value[i],bagDp[i - 1][j]); }else {//要记得这个处理 bagDp[i][j] = bagDp[i - 1][j]; } } } cout << bagDp[n][v] <<endl; return 0; }
空间压缩优化:O(VN)【但是空间是O(V)了】i物品存放本来是由i-1层跟新来的,但是如果j从V~1,因为dp[i][j]必然是由dp[i-1][j-v[i]]【也就是空间更小的更新来的】,我们就可以压缩一下,只需要一重dp[1~V]就成
#include <iostream> #include <cstring> using namespace std; const int N = 21; const int V = 1e3+10; int bagDp[V]; int value[N], volume[N]; int main() { int n, v; cin >> n >> v; for(int i = 1;i <= n;i++){ cin >> value[i] >> volume[i]; } for(int i = 1;i <= n;i++){ for(int j = v;j >= volume[i];j--){ bagDp[j] = max(bagDp[j-volume[i]] + value[i], bagDp[j]); } } cout << bagDp[v] <<endl; return 0; }
TYPE1 多重背包:
普通解法:
#include <iostream> #include <cstring> using namespace std; const int N = 21; const int V = 1e3+10; int bagDp[N][V]; int value[N], volume[N], quantity[N]; int main() { int n, v; cin >> n >> v; for(int i = 1; i <= n; i++) { cin >> value[i] >> volume[i] >> quantity[i]; } for(int i = 1; i <= n; i++) { for(int j = v; j >= volume[i]; j--) { for(int k = 0; k <= quantity[i]; k++) if(j >= volume[i]*k) bagDp[i][j] = max(bagDp[i-1][j-volume[i]*k] + value[i]*k, bagDp[i][j]); else break; } } cout << bagDp[n][v] <<endl; return 0; }
#include <iostream> #include <cstring> using namespace std; const int N = 21; const int V = 1e3+10; int bagDp[V]; int value[N], volume[N], quantity[N]; int main() { int n, v; cin >> n >> v; for(int i = 1; i <= n; i++) { cin >> value[i] >> volume[i] >> quantity[i]; } for(int i = 1; i <= n; i++)//总共有t组 从第一组开始 { for(int j = v; j >= volume[i]; j--)//背包容积剩余 j { for(int k = 0; k <= quantity[i]; k++)//这组里面有多少个元素 if(j >= volume[i]*k) bagDp[j] = max(bagDp[j-volume[i]*k] + value[i]*k, bagDp[j]); else break; } } cout << bagDp[v] <<endl; return 0; }
二进制优化:
根据把quantity[i]分解成二进制数来把其分成log(quantity[i])件物品
TYPE1 无穷背包:
用j来限制使得无穷背包转化为多重背包
甚至,都不用枚举k了,用dp[i][v-c[i]]更新dp[i][v]就行
空间优化:
#include <iostream> #include <cstring> using namespace std; const int N = 21; const int V = 1e3+10; int bagDp[V]; int value[N], volume[N]; int main() { int n, v; cin >> n >> v; for(int i = 1;i <= n;i++){ cin >> value[i] >> volume[i]; } for(int i = 1;i <= n;i++){ for(int j = volume[i];j <= v;j++){ bagDp[j] = max(bagDp[j-volume[i]] + value[i], bagDp[j]); } } cout << bagDp[v] <<endl; return 0; }
PART3(算法的延伸应用)
PART4(对算法深度的理解)
PART5(与其相关的有趣题目)