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:

ContractedBlock.gif ExpandedBlockStart.gif 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)
 8ExpandedBlockStart.gifContractedBlock.gif{
 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)
15ExpandedSubBlockStart.gifContractedSubBlock.gif    {
16        valueTable[itemIdx][0= 0;
17    }

18    // 初始化允许重量为0是的最大价值为0
19    for (int weightIdx = 0; weightIdx <= totalWeight; ++weightIdx)
20ExpandedSubBlockStart.gifContractedSubBlock.gif    {
21        valueTable[0][weightIdx] = 0;
22    }

23
24    // 从底层开始填写价值表和选择表
25    for (size_t itemIdx = 1; itemIdx <= length; ++itemIdx)
26ExpandedSubBlockStart.gifContractedSubBlock.gif    {
27        for (int weightIdx = 1; weightIdx <= totalWeight; ++weightIdx)
28ExpandedSubBlockStart.gifContractedSubBlock.gif        {
29            // 先计算不选择当前物品时的最大价值
30            int valueUnselected = valueTable[itemIdx - 1][weightIdx];
31            // 允许的重量需大于等于当前物品的重量,否则当前物品不可选
32            if (weightIdx >= weightArray[itemIdx - 1])
33ExpandedSubBlockStart.gifContractedSubBlock.gif            {
34                // 计算选择当前物品时的最大价值
35                int valueSelected = valueArray[itemIdx - 1+
36                                    valueTable[itemIdx - 1][weightIdx - weightArray[itemIdx - 1]];
37                // 若选择当前物品时所得到的最大价值大于不选择时的最大价值,
38                // 则选择当前物品,并进行下一次循环
39                if (valueSelected >= valueUnselected)
40ExpandedSubBlockStart.gifContractedSubBlock.gif                {
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)
57ExpandedSubBlockStart.gifContractedSubBlock.gif    {
58        if (selectionTable[itemIdx][weightIdx])
59ExpandedSubBlockStart.gifContractedSubBlock.gif        {
60            cout << itemIdx << " ";
61            weightIdx -= weightArray[itemIdx - 1];
62        }

63    }

64    cout << endl;
65}

66
67int main()
68ExpandedBlockStart.gifContractedBlock.gif{
69ExpandedSubBlockStart.gifContractedSubBlock.gif    int weights[] = {12322};
70ExpandedSubBlockStart.gifContractedSubBlock.gif    int values[] = {84053};
71    int totalWeight = 4;
72    Knapsack(weights, values, sizeof(weights) / sizeof(int), totalWeight);
73    return 0;
74}

 

     请各位批评、指正~

转载于:https://www.cnblogs.com/zyobi/archive/2009/06/22/1508730.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值