0-1背包问题(c/c++)

问题介绍:现在有一个可以载重w的背包和n个物品,每个物品的重量和价格分别为 wi vi ,请选择所装物品,使得在不超过背包载重的前提下,背包里的物品价格最高。

求解方案1:

#include
#include
using namespace std;
/*
w  背包最大载重
n  物品总数
ws 物品重量
vs 物品价值
res[i][j] 表示针对前i个物品,当背包的最大载重为j时,能放物品的最大价值
choice[i] =0表示第i个物品不选择
*/
int main()
{
    int w, n;
    cin >> w >> n;
    vector<int> ws;
    vector<int> vs;
    for (int i = 0; i < n; i++)
    {
        int tmpW, tmpV;
        cin >> tmpW >> tmpV;
        ws.push_back(tmpW);
        vs.push_back(tmpV);
    }
    vector<int> choice(n + 1, 0);
    int** res = new int* [n + 1];
    for (int i = 0; i <= n; i++)
    {
        res[i] = new int[w + 1];
    }
    //遍历所有的物品
    for (int i = 0; i <= n; i++)
    {
        for (int j = 0; j <= w; j++)
        {
            if (i == 0 || j == 0)
            {
                res[i][j] = 0;
            }
            else
            {
                if (j >= ws[i - 1]) //如果当前背包可以存放第i个物品
                {
                    //res[i][j]:对于前i个物品,当背包容量为j时的最大价值
                    //res[i-1][j],对于前(i-1)个物品,背包容量为j时的最大价值
                    //res[i-1][j-ws[i]],对于前(i-1)个物品,背包容量为j-ws[i-1]时的最大价值
                    res[i][j] = max(res[i - 1][j], res[i - 1][j - ws[i - 1]] + vs[i - 1]);
                }
                else
                {
                    res[i][j] = res[i - 1][j];
                }
            }
        }
    }
    int maxValue = res[n][w];
    int maxWeight = w;
    //输出选择方案
    while (maxValue)
    {
        for (int i = 1; i <= n; i++)
        {
            if (maxWeight >= ws[i - 1]
                    && (maxValue - res[n][maxWeight - ws[i - 1]]) == vs[i - 1])
            {
                choice[i] = 1;
                maxValue -= vs[i - 1];
                maxWeight -= ws[i - 1];
            }
        }
    }
    cout << "最优方案:" << endl;
    for (int i = 1; i <= n; i++)
    {
        if (choice[i] == 1)
        {
            cout << "选择物品:" << i << ",价格:" << vs[i - 1] << ",重量:" <<
                 ws[i - 1] << endl;
        }
    }
    cout << "The max value is " << res[n][w] << endl;
    for (int i = 0; i <= n; i++)
    {
        delete[] res[i];
    }
    return 0;
}

求解方案2:

#include
#include
using namespace std;
/*
w  背包最大载重
n  物品总数
ws 物品重量
vs 物品价值
res[j] 表示当背包的最大载重为j时,能放物品的最大价值
*/
int main()
{
    int w, n;
    vector<int> ws;
    vector<int> vs;
    vector<int> res(w + 1, 0);
    for (int i = 0; i < n; i++)
    {
        int tmpW, tmpV;
        cin >> tmpW >> tmpV;
        ws.push_back(tmpW);
        vs.push_back(tmpV);
    }
    //这里的i是代表前i个物品子集
    for (int i = 0; i < n; i++)
    {
        //这里为什么需要从w开始递减遍历?
        //仔细分析解决方案1可以发现,最后计算最大价值或者求解最优解决方案,都只用了res[n][:]这个维度的值。
        //所不同的是,解决方案1保留了所有历史信息,解决方案2是只保留上一次的历史信息,同时我们发现
        //res[j]的更新只会用到res[i](i
        for (int j = w; j > 0; j--)
        {
            if (j >= ws[i] && res[j] < (res[j - ws[i]] + vs[i]))
            {
                res[j] = res[j - ws[i]] + vs[i];
            }
        }
    }
    cout << "The max value is " << res[w] << endl;
    return 0;
}

你可能感兴趣的:(C++)