背包问题求解 C++版本实现

背包问题

1. 0-1背包问题

假设有n件物品和容量为m的背包,已知每件物品的重量及价值,在满足装入背包的物品重量最大的前提下,使得装入物品的总价值最大。
(1) 二维动态规划

d p [ i ] [ j ] = m a x ( d p [ i − 1 ] [ j ] , d p [ i − 1 ] [ j − w e i g h t s [ i ] ] + v a l u e s [ i ] ) dp[i][j]=max(dp[i-1][j], dp[i-1][j-weights[i]]+values[i]) dp[i][j]=max(dp[i1][j],dp[i1][jweights[i]]+values[i])

(2) 一维动态规划

d p [ j ] = m a x ( d p [ j ] , d p [ j − w e i g h t s [ i ] ] + v a l u e s [ i ] ) dp[j] = max(dp[j], dp[j - weights[i]] + values[i]) dp[j]=max(dp[j],dp[jweights[i]]+values[i])

#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;

//二维动态规划
int knapsack2(int n, int m, vector<int> &weights, vector<int> &values) {
	vector<vector<int>> dp(n + 1, vector<int>(m + 1, 0));
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= m; j++) {
			if (weights[i] > j) dp[i][j] = dp[i - 1][j];
			else dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - weights[i]] + values[i]);
		}
	}
	return dp[n][m];
}

//一维动态规划
int knapsack1(int n, int m, vector<int> &weights, vector<int> &values) {
	vector<int> dp(m + 1, 0);
	for (int i = 1; i <= n; i++) {
		for (int j = m; j >= weights[i]; j--) {
			dp[j] = max(dp[j], dp[j - weights[i]] + values[i]);
		}
	}
	return dp[m];
}

int main() {
	int n, m;
	cin >> n >> m;
	vector<int> weights(n + 1, 0);
	vector<int> values(n + 1, 0);
	for (int i = 1; i <= n; i++) cin >> weights[i];
	for (int i = 1; i <= n; i++) cin >> values[i];
	cout << knapsack1(n, m, weights, values) << endl;
	//cout << knapsack2(n, m, weights, values) << endl;
}

2. 完全背包问题

在0-1背包问题的基础上,每个物品的数量均为无限个。

d p [ j ] = m a x ( d p [ j ] , d p [ j − w e i g h t s [ i ] ] + v a l u e s [ i ] ) dp[j] = max(dp[j], dp[j - weights[i]] + values[i]) dp[j]=max(dp[j],dp[jweights[i]]+values[i])

int knapsack3(int n, int m, vector<int> &weights, vector<int> &values) {
	vector<int> dp(m + 1, 0);
	for (int i = 1; i <= n; i++) {
		for (int j = weights[i]; j <= m; j++) {
			dp[j] = max(dp[j], dp[j - weights[i]] + values[i]);
		}
	}
	return dp[m];
}

3. 多重背包问题

在0-1背包问题的基础上,每个物品的数量有限。

d p [ j ] = m a x ( d p [ j ] , d p [ j − k ∗ w e i g h t s [ i ] ] + k ∗ v a l u e s [ i ] ) dp[j] = max(dp[j], dp[j - k * weights[i]] + k * values[i]) dp[j]=max(dp[j],dp[jkweights[i]]+kvalues[i])

int knapsack4(int n, int m, vector<int> &weights, vector<int> &values, vector<int> &nums) {
	vector<int> dp(m + 1, 0);
	for (int i = 1; i <= n; i++) {
		for (int j = m; j >= weights[i]; j--) {
			for (int k = 0; k <= nums[i]; k++) {
				if (j - k * weights[i] < 0) break;
				dp[j] = max(dp[j], dp[j - k * weights[i]] + k * values[i]);
			}
		}
	}
	return dp[m];
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值