完全背包问题的几种求解方法
C++
完全背包问题
/* * 完全背包问题 * 问题描述: * 有 N 种物品和一个容量是 V 的背包,每种物品都有无限件可用。 * 第 i 种物品的体积是 vi,价值是 wi。 * 求解将哪些物品装入背包,可使这些物品的总体积不超过背包容量,且总价值最大。 * 输出最大价值。 * * 数据范围: * 0 < N, V ≤ 1000 * 0 < vi, wi ≤ 1000 * 背包问题都是算法的经典题目,下面给出 完全背包 问题的解题思路: * * 解题思路1: * 数组定义: * f[i][j] 表示前 i 个物品,体积为 j 的最大价值 * 递归方程: * f[i][j] = max(f[i-1][j], f[i-1][j-vi]+wi, f[i-1][j-2vi]+2wi, f[i-1][j-3vi]+3wi, ..., f[i-1][j-kvi]+kwi k=j//vi) * max(f[i-1][j], f[i][j-vi]+wi) * 初始化结果: * memset(f, 0xcf, sizeof f); * f[0][0] = 0 * 最终结果 * max(f[n][0], f[n][1], ..., f[n][m]) * 复杂度分析: * 时间复杂度为 O(NM) * tips: * 可以使用滚动数组,或者是变换内部循环顺序,将空间复杂度优化到 O(M) * 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]); * } * } * * 解题思路2: * 数组定义: * f[i][j] 表示前 i 个物品,体积小于等于为 j 的最大价值 * 递归方程: * f[i][j] = max(f[i-1][j], f[i-1][j-vi]+wi, f[i-1][j-2vi]+2wi, f[i-1][j-3vi]+3wi, ..., f[i-1][j-kvi]+kwi k=j//vi) * max(f[i-1][j], f[i][j-vi]+wi) * 初始化结果: * memset(f, 0, sizeof f); * 最终结果 * f[n][m] * 复杂度分析: * 时间复杂度为 O(NM) * tips: * 可以使用滚动数组,或者是变换内部循环顺序,将空间复杂度优化到 O(M) * 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]); * } * } * * 解题思路3: * 数组定义: * f[i][j] 表示前 i 个物品,价值等于 j 的最小体积 * 递归方程: * f[i][j] = min(f[i-1][j], f[i-1][j-wi]+vi, f[i-1][j-2wi]+2vi, f[i-1][j-3wi]+3vi, ..., f[i-1][j-kwi]+kvi k=j//vi) * = min(f[i-1][j], f[i][j-wi]+vi) * 初始化结果: * memset(f, 0x3f, sizeof f); INF * f[0][0] = 0 * 最终结果 * 便利f[n][0-W] W 为最大的可能价值,找到满足 体积 m 的价值。 * 复杂度分析: * 时间复杂度为 O(NW),本题而言 W 过高 * tips: * 可以使用滚动数组,或者是变换内部循环顺序,将空间复杂度优化到 O(M) * * 解题思路4: * 数组定义: * f[i][j] 表示前 i 个物品,价值大于等于 j 的最小体积 * 这个需要注意状态为 负数的时候,是合法的。 */ #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int N = 1010, M = N; const int INF = 0x3f3f3f3f, _INF = 0xcfcfcfcf; int n, m; int f[N][M]; int v[N], w[N]; int solution_one() { memset(f, 0xcf, sizeof f); f[0][0] = 0; for (int i = 1; i <= n; i ++ ) { for (int j = 0; j <= m; j ++ ) { if (j >= v[i]) { f[i][j] = max(f[i - 1][j], f[i][j - v[i]] + w[i]); } else { f[i][j] = f[i - 1][j]; } } } int res = _INF; for (int i = 0; i <= m; i ++ ) { res = max(res, f[n][i]); } return res; } int solution_two() { memset(f, 0, sizeof f); for (int i = 1; i <= n; i ++ ) { for (int j = 0; j <= m; j ++ ) { if (j >= v[i]) { f[i][j] = max(f[i - 1][j], f[i][j - v[i]] + w[i]); } else { f[i][j] = f[i - 1][j]; } } } int res = f[n][m]; return res; } int main() { scanf("%d%d", &n, &m); for (int i = 1; i <= n; i ++ ) { scanf("%d%d", &v[i], &w[i]); } int res = solution_one(); printf("%d\n", res); return 0; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)