0-1背包问题是一个经典的动态规划问题,问题定义如下:有n个物品,其重量分别为W={w1, w1, w3, ... wn},其价值分别为V={v1, v2, v3, .. vn}。现在要将这N个物品放入允许的最大重量为w的包中,问怎样选择物品能使包中的物品总价值最大。
可以将背包问题划分成若干个子问题,关键在于如何对问题进行划分。现在将问题表述为在重量限制为w的情况下,求对前N个物品进行选择能得到的最大价值,即v[n, w]。对于一个物品i,求v[i, w']时有两种情况可供选择:若选中物品i,则所得的最大价值为v[i-1, w'-wi]+vi;若不选中物品i,则所得的最大价值为v[i-1, w']。选择二者之间的较大值即可求出最优解。因此,子问题可以分解成两个更小的子问题。
解决0-1背包问题的C++代码如下所示, 代码中用到了boost库中的multi_array:
1
#include <iostream>2
#include <boost/multi_array.hpp>3

4
using namespace std;5

6
// 动态规划解决0-1背包问题7
void Knapsack(int weightArray[], int valueArray[], size_t length, int totalWeight)8


{9
// 价值表10
boost::multi_array<int, 2> valueTable(boost::extents[length + 1][totalWeight + 1]);11
// 选择表12
boost::multi_array<bool, 2> selectionTable(boost::extents[length + 1][totalWeight + 1]);13
// 初始化前0个物品的最大价值为014
for (size_t itemIdx = 0; itemIdx <= length; ++itemIdx)15

{16
valueTable[itemIdx][0] = 0;17
}18
// 初始化允许重量为0是的最大价值为019
for (int weightIdx = 0; weightIdx <= totalWeight; ++weightIdx)20

{21
valueTable[0][weightIdx] = 0;22
}23

24
// 从底层开始填写价值表和选择表25
for (size_t itemIdx = 1; itemIdx <= length; ++itemIdx)26

{27
for (int weightIdx = 1; weightIdx <= totalWeight; ++weightIdx)28

{29
// 先计算不选择当前物品时的最大价值30
int valueUnselected = valueTable[itemIdx - 1][weightIdx];31
// 允许的重量需大于等于当前物品的重量,否则当前物品不可选32
if (weightIdx >= weightArray[itemIdx - 1])33

{34
// 计算选择当前物品时的最大价值35
int valueSelected = valueArray[itemIdx - 1] +36
valueTable[itemIdx - 1][weightIdx - weightArray[itemIdx - 1]];37
// 若选择当前物品时所得到的最大价值大于不选择时的最大价值,38
// 则选择当前物品,并进行下一次循环39
if (valueSelected >= valueUnselected)40

{41
valueTable[itemIdx][weightIdx] = valueSelected;42
selectionTable[itemIdx][weightIdx] = true;43
continue;44
}45
}46

47
// 处理不选择当前物品的情况48
valueTable[itemIdx][weightIdx] = valueUnselected;49
selectionTable[itemIdx][weightIdx] = false;50
}51
}52

53
// 打印最大值以及被选中的物品编号54
cout << "最大价值为:" << valueTable[length][totalWeight] << endl;55
cout << "以下编号的物品被选中:";56
for (size_t itemIdx = length, weightIdx = totalWeight; itemIdx > 0; --itemIdx)57

{58
if (selectionTable[itemIdx][weightIdx])59

{60
cout << itemIdx << " ";61
weightIdx -= weightArray[itemIdx - 1];62
}63
}64
cout << endl;65
}66

67
int main()68


{69

int weights[] =
{1, 2, 3, 2, 2};70

int values[] =
{8, 4, 0, 5, 3};71
int totalWeight = 4;72
Knapsack(weights, values, sizeof(weights) / sizeof(int), totalWeight);73
return 0;74
}
本文介绍了0-1背包问题,这是一个经典的动态规划问题,涉及如何在有限重量限制下选择物品以最大化总价值。通过动态规划策略,将问题分解为求解前N个物品在特定重量限制下的最大价值。文章提供了采用C++和boost库的multi_array实现的代码示例。
4万+

被折叠的 条评论
为什么被折叠?



