(2)动态规划:01背包、完全背包、多重背包,源代码由C++实现

这篇博客介绍了如何使用动态规划解决三种背包问题:01背包、完全背包和多重背包。针对每种问题,详细阐述了问题描述、算法分析,并提供了核心代码和测试用例,帮助理解动态规划在背包问题中的应用。
摘要由CSDN通过智能技术生成


背包问题是动态规划算法的一个典型实例。

1. 01背包问题

1.1 问题描述与算法分析

01背包问题描述:有编号分别为a,b,c,d,e的五件物品,它们的重量分别是2,2,6,5,4,它们的价值分别是6,3,5,4,6,每件物品数量只有一个,现在给你个承重为10的背包,如何让背包里装入的物品具有最大的价值总和?

动态规划的基本思路:将该问题转换成子问题,考虑五件物品在给定承重 C 的背包下最大价值为原问题,如下表所示,即为考虑abcde,C = 10时的最大价值,假设为f[5][10],原问题的解可以分解为两种情况,第一种情况是不考虑放入a只考虑放入bcde承重为C时的最大价值f[4][C],第二种情况是考虑放入a时的最大价值,即value[a]+f[4][10-weight[a]]。 原问题的解f[5][10]取上述两种情况中的最大值,即f[5][10] = max{f[4][10], (f[4][10-weight[a]+value[a]))}。 由此可以看出里面涉及到需要计算f[4][10]和f[4][10-weight[a]]即f[4][4]等子问题。 以此类推,自顶向下的分析可以看出原问题需要子问题的解,我们需要先计算出子问题的解,自底向上求解。求解方式如下表所示,顺序是自底向上、从左往右,或者从左往右、自底向上都可以。注意此问题中的abcde可以包含相同的物件,它们之间的顺序也可以是任意的,不影响最终的结果。
在这里插入图片描述

1.2 核心代码
vector<vector<int>>& knapsack01(
		vector<pair<int, int>> &goodsVec, int packageVol)
{
   
	if (goodsVec.empty())
	{
   
		throw "Invalid arg : goodsVec empty";
	}

	if (packageVol < 0 || packageVol > 1000)
	{
   
		throw "Invalid arg : packageVol out of range";
	}

	//动态规划的二维数组
	static vector<vector<int>>dpValue(
			goodsVec.size(), vector<int>(packageVol + 1, 0));
	for (unsigned i = 0; i < dpValue.size(); ++i)
	{
   
		for (unsigned j = 0; j < dpValue[0].size(); ++j)
		{
   
			int volume = j;
			if (0 == i) //只有一种物品时
			{
   
				dpValue[i][j] = goodsVec[i].first <= volume ? goodsVec[i].second : 0;
			}
			else if (0 == j) //背包容量为0时
			{
   
				dpValue[i][j] = 0;
			}
			else //背包容量和物品种数都>=1时,使用递推公式
			{
   
				//背包容量volume不能容纳一件物品weight[i]
				if (volume < goodsVec[i].first)	
				{
   
					dpValue[i][j] = dpValue[i - 1][j];
				}
				else //背包容量volume能容纳一件物品weight[i]
				{
   
					int value = dpValue[i - 1][volume - goodsVec[i].first] 
							+ goodsVec[i].second;
					dpValue[i][j] = max(dpValue[i - 1][j], value);
				}
			}
		} //for 2
	} //for 1

	return dpValue;
}
1.3 测试代码
#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

void printDPValue(vector<vector<int>> &dpValue)
{
   
	if (dpValue.empty())
	{
   
		throw "Invalid arg : dpValue empty";
	}

	for (unsigned i = 0; i < dpValue.size(); ++i)
	{
   
		for (unsigned j = 0; j < dpValue[0].size(); ++j)
		{
   
			cout << dpValue[i][j] << " ";
		}
		cout << endl;
	}
}

//此处用上述核心代码替换
vector<vector<int>&
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值