背包
背包问题
01背包:每个物品:选、不选
完全背包:每个物品:选0,选1个,选2个,....选无穷多个
多重背包问题(每个物品:选0....选si个)
多重背包问题Ⅰ(朴素版):
点击查看代码
// 数据范围 // 0<N,V≤100 // 0<vi,wi,si≤100 #include<iostream> using namespace std; const int N = 110; int v[N], w[N], s[N]; int m, n; int f[N][N]; int main() { // 物品种数 背包容积 cin >> m >> n; for (int i = 1; i <= m; i++) { cin >> v[i] >> w[i] >> s[i]; } for (int i = 1; i <= m; i++) { for (int j = 0; j <= n; j++) { for (int k = 0; k <= s[i] && k * v[i] <= j; k++) { f[i][j] = max(f[i][j], f[i-1][j-k*v[i]] + w[i]*k); } } } cout << f[m][n] << endl; return 0; }
多重背包问题Ⅱ(对多重背包问题Ⅰ进行二进制的优化):
点击查看代码
// 数据范围 // 0<N≤1000 // 0<V≤2000 // 0<vi,wi,si≤2000 #include<iostream> #include<algorithm> using namespace std; // 时间复杂度为N * V * logS= 1000 * 2000 * log2000 const int N = 25000; int m, n; int v[N], w[N], s[N]; int f[N]; int main() { // 物品种数 背包容积 cin >> m >> n; // 当前物品的排序 int cnt = 0; for (int i = 1; i <= n; i++) { int a, b, c; // 表示体积 价值 数量 cin >> a >> b >> c; // k表示当前选择当前物品的个数 int k = 1; // 当选择物品个数大于给定个数时,退出循环 while (k <= c) { cnt++; v[cnt] = a * k; w[cnt] = b * k; c -= k; k *= 2; } // 当还有剩余值时,继续加进来 if (c > 0) { cnt++; v[cnt] = a * c; w[cnt] = b * c; } } // 更新物品的个数 m = cnt; // 将多重背包问题变成了01背包 // 对于每个组中的物品选或是不选 for (int i = 1; i <= m; i++) { for (int j = n; j >= v[i]; j--) { f[j] = max(f[j], f[j-v[i]] + w[i]); } } cout << f[n]; return 0; }
多重背包问题Ⅲ(对多重背包问题Ⅰ进行单调队列优化/滑动窗口求数值):(不太懂)
点击查看代码
#include<iostream> #include<algorithm> #include<cstring> using namespace std; const int N = 20010; int n, m; int f[N], g[N], q[N]; int main() { // 分别表示物品种数 背包体积 cin >> n >> m; for (int i = 0; i < n; i++) { int v, w, s; cin >> v >> w >> s; // 将i-1层(上一层)的价值存储下来 memcpy(g, f, sizeof f); for (int j = 0; j < v; j++) { int hh = 0, tt = -1; for (int k = j; k <= m; k += v) { // 当整个队列中的元素超出s个时,就让队头元素出去 if (hh <= tt && q[hh] < k - s * v) { hh++; } // 下标减去初始的值 // 将尾部元素的价值比当前的元素的价值小的时候,将队尾弹出 // 当前下标和该最大值的下标之间差了x个v,那么就要加上x个w while (hh <= tt && g[q[tt]] - (q[tt] - j) / v * w <= g[k] - (k - j) / v * w) { tt--; } // 如果队列不空的话,求得的是窗口内部的最大值。中间空余了x个物品,将x乘以w if (hh <= tt) { f[k] = max(f[k], g[q[hh]] + (k - q[hh]) / v * w); } q[++tt] = k; } } } cout << f[m] << endl; return 0; }
本文来自博客园,作者:jsqup,转载请注明原文链接:https://www.cnblogs.com/jsqup/p/16229605.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?