完全背包问题的几种求解方法
作者:互联网
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;
}
标签:背包,求解,int,max,wi,几种,vi,物品 来源: https://www.cnblogs.com/lucky-light/p/16436982.html