0-1背包问题(C++)

     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:

0-1背包问题
 1#include <iostream>
 2#include <boost/multi_array.hpp>
 3
 4using namespace std;
 5
 6// 动态规划解决0-1背包问题
 7void Knapsack(int weightArray[], int valueArray[], size_t length, int totalWeight)
 8{
 9    // 价值表
10    boost::multi_array<int2> valueTable(boost::extents[length + 1][totalWeight + 1]);
11    // 选择表
12    boost::multi_array<bool2> selectionTable(boost::extents[length + 1][totalWeight + 1]);
13    // 初始化前0个物品的最大价值为0
14    for (size_t itemIdx = 0; itemIdx <= length; ++itemIdx)
15    {
16        valueTable[itemIdx][0= 0;
17    }

18    // 初始化允许重量为0是的最大价值为0
19    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
67int main()
68{
69    int weights[] = {12322};
70    int values[] = {84053};
71    int totalWeight = 4;
72    Knapsack(weights, values, sizeof(weights) / sizeof(int), totalWeight);
73    return 0;
74}

 

     请各位批评、指正~

你可能感兴趣的:(0-1背包问题(C++))