背包问题

1.01背包问题

https://blog.csdn.net/xp731574722/article/details/70766804

https://www.cnblogs.com/Christal-R/p/Dynamic_programming.html

/*01背包问题*/
#include<iostream>
#include<vector>
#include<algorithm>

using namespace std;

//找不超过容量的最大价值
void Findmax(vector<int>&v, vector<int>&c, int C, vector<vector<int>>&dp){                                                        
    for (int i = 1; i <v.size(); i++){
        for (int j = 1; j <=C; j++){
            if (c[i] > j){
                dp[i][j] = dp[i - 1][j];//如果第i件物品所占容量大于当前背包容量,则不放入
            }
            else{
                dp[i][j] = max(dp[i - 1][j],dp[i-1][j-c[i]]+v[i]);//选择不放入第i个,和放入第i个后价值最大的
            }
        }
    }

}

//找选择的物品的序号
void Findpos(int i, int j, vector<int>&v, vector<int>&c, vector<int>&item, vector<vector<int>>&dp)
{
    if (i > 0)
    {
        //cout << dp[i][j] << endl;
        //cout << dp[i - 1][j - c[i]] + v[i];

        if (dp[i][j] == dp[i - 1][j])//相等说明没装第i件商品
        {
            item[i] = 0;//全局变量,标记未被选中
            Findpos(i - 1, j,v,c,item,dp);
        }
        
        else if (j - c[i] >= 0 && dp[i][j] == dp[i - 1][j - c[i]] + v[i])
        {
            item[i] = 1;//标记已被选中
            //cout << i << endl;
            //cout << j << endl;
            Findpos(i - 1, j - c[i],v,c,item,dp);//回到装包之前的位置
        }
    }
}


int main(){
    vector<int>v = { 0, 60, 100, 120 };//每件物品对应价值
    vector<int>c = { 0, 1, 2, 3 };//每件物品所占容量,第一个零是为了方面从序号1开始所以补的
    int C = 5;
    vector<vector<int>>res(v.size(), vector<int>(C+1, 0));//res[i][j]代表前i件物品恰放入容量j(还能装j的容量)的背包的最大价值
    Findmax(v, c, C,res);
    //填表
    for (int i = 0; i < res.size(); i++){
        for (int j = 0; j < res[0].size(); j++){
            cout << res[i][j] << " ";
        }
        cout << endl;
    }
    cout << res[v.size()-1][C] << endl;//最大价值
    vector<int>item(v.size(), 0);
    Findpos(v.size() - 1, C, v, c, item, res);
    for (int i = 0; i < item.size(); i++){
        if (item[i] != 0){
            cout << i<< endl;
        }
    }
    system("pause");
    return 0;
}

 2.完全背包问题

https://blog.csdn.net/na_beginning/article/details/62884939

/*完全背包问题*/
#include<iostream>
#include<vector>
#include<algorithm>

using namespace std;

//找不超过容量的最大价值
void Findmax(vector<int>&v, vector<int>&c, int C, vector<vector<int>>&dp){                                                        
    for (int i = 1; i <v.size(); i++){
        for (int j = 1; j <=C; j++){
            if (c[i] > j){
                dp[i][j] = dp[i - 1][j];//如果第i件物品所占容量大于当前背包容量,则不放入
            }
            else{
                dp[i][j] = max(dp[i - 1][j],dp[i][j-c[i]]+v[i]);//此处与01背包区别
            }
        }
    }

}

//找选择的物品的序号
void Findpos(int i, int j, vector<int>&v, vector<int>&c, vector<int>&item, vector<vector<int>>&dp)
{
    if (i > 0)
    {
        //cout << dp[i][j] << endl;
        //cout << dp[i - 1][j - c[i]] + v[i];

        if (dp[i][j] == dp[i - 1][j])//相等说明没装第i件商品
        {
            item[i] = 0;//全局变量,标记未被选中
            Findpos(i - 1, j,v,c,item,dp);
        }
        
        else if (j - c[i] >= 0 && dp[i][j] == dp[i - 1][j - c[i]] + v[i])
        {
            item[i] = 1;//标记已被选中
            //cout << i << endl;
            //cout << j << endl;
            Findpos(i - 1, j - c[i],v,c,item,dp);//回到装包之前的位置
        }
    }
}


int main(){
    vector<int>v = { 0, 1, 3, 5,9 };//每件物品对应价值
    vector<int>c = { 0, 2, 3, 4,7 };//每件物品所占容量,第一个零是为了方面从序号1开始所以补的
    int C = 10;
    vector<vector<int>>res(v.size(), vector<int>(C+1, 0));//res[i][j]代表前i件物品恰放入容量j(还能装j的容量)的背包的最大价值
    Findmax(v, c, C,res);
    //填表
    for (int i = 0; i < res.size(); i++){
        for (int j = 0; j < res[0].size(); j++){
            cout << res[i][j] << " ";
        }
        cout << endl;
    }
    cout << res[v.size()-1][C] << endl;//最大价值
    vector<int>item(v.size(), 0);
    Findpos(v.size() - 1, C, v, c, item, res);
    for (int i = 0; i < item.size(); i++){
        if (item[i] != 0){
            cout << i<< endl;
        }
    }
    system("pause");
    return 0;
}

 

posted @ 2018-06-25 15:18  追逐更好的自己  阅读(150)  评论(0编辑  收藏  举报