蓝桥杯 算法训练 完全背包问题

最近刚开始刷dp的题目,留下这篇文章以作纪念。

 dp[i][j]的含义为前0~i个物品放到容量j的背包里的最大价值

首先,容量为0以及物品数量为0的情况价值必定为0

所以我们可以初始化dp数组的第一行以及第一列的值为0

dp[i][j]的可以分两种情况讨论:

        1.不选择物品i,那么价值为0~i-1个物品放入容量j的背包的最大价值,即dp[i-1][j]

        2.选择物品i,物品i可选择k个,k个i物品为的价值为v[i]*k,剩下的容量j-k*w[i]装入0~i-1个物品,

        那么此时价值就是    v[i]*k+dp[i-1][j-k*w[i]]

我们只需取两种情况的最大值即可。

重量需排序后才能做

#include <iostream>
using namespace std;
int dp[1001][1001];//dp[i][j]表示前i个物品放到容量j的背包里的最大价值

int main() {
	int N, M;
	cin >> N >> M;
	int W[N + 1], V[N + 1];
	for (int i = 1; i <= N; i++) {
		cin >> W[i] >> V[i];
	}
	for (int i = 0; i <= 1001; i++) {//当容量为0或个数为0时没有价值
		dp[i][0] = dp[0][i] = 0;
	}
	for (int i = 1; i <= N - 1; i++) {//简单的冒泡排序
		for (int j = 1; j <= N - i; j++) {
			if (W[j] > W[j + 1]) {
				int temp = W[j];
				W[j] = W[j + 1];
				W[j + 1] = temp;

				temp = V[j];
				V[j] = V[j + 1];
				V[j + 1] = temp;
			}
		}
	}
	//核心代码
	for (int i = 1; i <= N; i++) {
		for (int j = 1; j <= M; j++) {
			dp[i][j] = dp[i - 1][j];//不选第i个物品时
			for (int k = 1; k <= j / W[i]; k++) {
				int A = dp[i - 1][j - k * W[i]] + k * V[i];//选k个物品i时的价值
				dp[i][j] = dp[i][j] > A ? dp[i][j] : A;
			}
		}
	}
	cout << dp[N][M];
}

如有不足,望多加以批评

  • 4
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值