背包问题
背包问题
背包问题是使用dp的经典问题,本篇文章将讲解所有的背包问题,文章也会不断完善,不断通俗易懂。
背包问题是使用dp的经典问题,本篇文章将讲解所有的背包问题,文章也会不断完善,不断通俗易懂。
背包问题是使用dp的经典问题,本篇文章将讲解所有的背包问题,文章也会不断完善,不断通俗易懂。
背包问题是使用dp的经典问题,本篇文章将讲解所有的背包问题,文章也会不断完善,不断通俗易懂。
01背包
Acwing 2. 01背包问题
空间未优化版本
#include<bits/stdc++.h> using namespace std; const int N = 1e3 + 10; int v[N], w[N], f[N][N]; int main(){ int n, m; scanf("%d%d", &n, &m); for(int i = 1; i <= n; i ++ ){ scanf("%d%d", &v[i], &w[i]); } for(int i = 1; i <= n; i ++ ){ for(int j = 1; j <= m; j ++ ){ if(j < v[i]) f[i][j] = f[i - 1][j]; else f[i][j] = max(f[i - 1][j], f[i - 1][j - v[i]] + w[i]); } } printf("%d", f[n][m]); return 0; }
空间优化版本
#include<bits/stdc++.h> using namespace std; const int N = 1e3 + 10; int v[N], w[N], f[N]; int main(){ int n, m; scanf("%d%d", &n, &m); for(int i = 1; i <= n; i ++ ){ scanf("%d%d", &v[i], &w[i]); } for(int i = 1; i <= n; i ++ ){ for(int j = m; j >= v[i]; j -- ){ f[j] = max(f[j], f[j - v[i]] + w[i]); } } printf("%d", f[m]); return 0; }
完全背包
Acwing 3. 完全背包问题
空间未优化版本
#include<bits/stdc++.h> using namespace std; const int N = 1e3 + 10; int v[N], w[N], f[N][N]; int main(){ int n, m; scanf("%d%d", &n, &m); for(int i = 1; i <= n; i ++ ){ scanf("%d%d", &v[i], &w[i]); } for(int i = 1; i <= n; i ++ ){ for(int j = 1; j <= m; j ++ ){ if(j < v[i]) f[i][j] = f[i - 1][j]; else f[i][j] = max(f[i - 1][j], f[i][j - v[i]] + w[i]); } } printf("%d", f[n][m]); return 0; }
空间优化版本
#include<bits/stdc++.h> using namespace std; const int N = 1e3 + 10; int v[N], w[N], f[N]; int main(){ int n, m; scanf("%d%d", &n, &m); for(int i = 1; i <= n; i ++ ){ scanf("%d%d", &v[i], &w[i]); } for(int i = 1; i <= n; i ++ ){ for(int j = v[i]; j <= m; j ++ ){ f[j] = max(f[j], f[j - v[i]] + w[i]); } } printf("%d", f[m]); return 0; }
多重背包(TODO)
#include<bits/stdc++.h> using namespace std; const int N = 1e2 + 10; int v[N], w[N], s[N], f[N][N]; int main(){ int n, m; scanf("%d%d", &n, &m); for(int i = 1; i <= n; i ++ ) scanf("%d%d%d", &v[i], &w[i], &s[i]); for(int i = 1; i <= n; i ++ ){ for(int j = 1; j <= m; j ++ ){ for(int k = 0; k <= s[i] && j >= k * v[i]; k ++ ){ f[i][j] = max(f[i][j], f[i - 1][j - k * v[i]] + k * w[i]); } } } printf("%d", f[n][m]); return 0; }
空间优化版本
#include<bits/stdc++.h> using namespace std; const int N = 1e2 + 10; int v[N], w[N], s[N], f[N]; int main(){ int n, m; scanf("%d%d", &n, &m); for(int i = 1; i <= n; i ++ ) scanf("%d%d%d", &v[i], &w[i], &s[i]); for(int i = 1; i <= n; i ++ ){ for(int j = m; j >= v[i]; j -- ){ for(int k = 1; k <= s[i] && j >= k * v[i]; k ++ ){ // k 只取到1就可以了,因为f[j]代表了上一次循环的旧值和迭代1~s[i]的最大f[j] f[j] = max(f[j], f[j - k * v[i]] + k * w[i]); } } } printf("%d", f[m]); return 0; }
二进制优化版本
#include<bits/stdc++.h> using namespace std; const int N = 2e4 + 10; // log(2000) * 1000 = 11000 int v[N], w[N], f[N][N], num; int main(){ int n, m, vv, ww, s; scanf("%d%d", &n, &m); while(n -- ){ scanf("%d%d%d", &vv, &ww, &s); for(int k = 1; k <= s; k <<= 1){ v[ ++ num] = k * vv; w[num] = k * ww; s -= k; } if(s){ v[ ++ num] = s * vv; w[num] = s * ww; } } for(int i = 1; i <= num; i ++ ){ for(int j = 1; j <= m; j ++ ){ if(j < v[i]) f[i][j] = f[i - 1][j]; else f[i][j] = max(f[i - 1][j], f[i - 1][j - v[i]] + w[i]); } } printf("%d", f[num][m]); return 0; }
内存溢出
Memory Limit Exceeded
二进制优化版本,内存优化
#include<bits/stdc++.h> using namespace std; const int N = 1e4 + 2000; // log(2000) * 1000 = 11000 int v[N], w[N], f[N], num; int main(){ int n, m, vv, ww, s; scanf("%d%d", &n, &m); while(n -- ){ scanf("%d%d%d", &vv, &ww, &s); for(int k = 1; k <= s; k <<= 1){ v[ ++ num] = k * vv; w[num] = k * ww; s -= k; } if(s){ v[ ++ num] = s * vv; w[num] = s * ww; } } for(int i = 1; i <= num; i ++ ){ for(int j = m; j >= v[i]; j -- ){ f[j] = max(f[j], f[j - v[i]] + w[i]); } } printf("%d", f[m]); return 0; }
混合背包问题
Acwing 7. 混合背包问题
解法1
#include<bits/stdc++.h> using namespace std; const int N = 1e4 + 10; int f[N], v[N], w[N], s[N], num; int main(){ int n, m, vv, ww, ss; scanf("%d%d", &n, &m); while(n -- ){ scanf("%d%d%d", &vv, &ww, &ss); if(ss == 0){ v[ ++ num] = vv; w[num] = ww; s[num] = 0; // 完全背包 }else{ if(ss == -1) ss = 1; // 01 按照 特殊多重背包处理,统一转01背包 for(int k = 1; k <= ss; k <<= 1){ v[ ++ num] = k * vv; w[num] = k * ww; s[num] = 1; // 01背包 ss -= k; } if(ss){ v[ ++ num] = ss * vv; w[num] = ss * ww; s[num] = 1; // 01背包 } } } for(int i = 1; i <= num; i ++ ){ if(s[i] == 1){ // 01 背包 for(int j = m; j >= v[i]; j -- ){ f[j] = max(f[j], f[j - v[i]] + w[i]); } }else{ // 完全背包 for(int j = v[i]; j <= m; j ++ ){ f[j] = max(f[j], f[j - v[i]] + w[i]); } } } printf("%d", f[m]); return 0; }
解法二
#include<bits/stdc++.h> using namespace std; const int N = 1e3 + 10; int f[N], g[N], q[N], h, t; int n, m; void zero_one_pack(int v, int w){ for(int j = m; j >= v; j -- ) f[j] = max(f[j], f[j - v] + w); } void complete_pack(int v, int w){ for(int j = v; j <= m; j ++ ) f[j] = max(f[j], f[j - v] + w); } void multiple_pack(int v, int w, int s){ memcpy(g, f, sizeof f); for(int j = 0; j < v; j ++ ){ h = 0, t = -1; for(int k = j; k <= m; k += v){ while(h <= t && g[k] >= g[q[t]] + (k - q[t]) / v * w) t -- ; q[ ++ t] = k; if(h <= t && q[h] < k - s * v) h ++ ; f[k] = g[q[h]] + (k - q[h]) / v * w; } } } int main(){ int v, w, s; scanf("%d%d", &n, &m); while(n -- ){ scanf("%d%d%d", &v, &w, &s); if(s == -1) zero_one_pack(v, w); // 01背包 else if(s == 0) complete_pack(v, w); // 完全背包 else multiple_pack(v, w, s); // 多重背包 } printf("%d", f[m]); return 0; }
二维费用背包
#include<bits/stdc++.h> using namespace std; const int N = 1e3 + 10; int f[N][N]; int main(){ int N, V, M, v, m, w; scanf("%d%d%d", &N, &V, &M); while(N -- ){ scanf("%d%d%d", &v, &m, &w); // 体积、重量、价值 for(int j = V; j >= v; j -- ){ for(int k = M; k >= m; k -- ){ f[j][k] = max(f[j][k], f[j - v][k - m] + w); } } } printf("%d", f[V][M]); return 0; }
分组背包
TODO
本文作者:爱情丶眨眼而去
本文链接:https://www.cnblogs.com/zshsboke/p/17860226.html
版权声明:本作品采用©️CC BY-NC-SA 4.0许可协议进行许可。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步