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

来源:互联网 发布:iphone数据开关快捷键 编辑:程序博客网 时间:2024/04/29 09:11

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

求解方案1:

#include<iostream>#include<vector>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<iostream>#include<vector>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<j)的历史数据,所以从大到校遍历w才不会过早覆盖历史数据;        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;}
0 0
原创粉丝点击