揹包問題

1.01揹包問題

http://www.javashuo.com/article/p-fpwumjto-mv.htmlhtml

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

/*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.徹底揹包問題

http://www.javashuo.com/article/p-uqccgsnr-na.htmlspa

/*徹底揹包問題*/
#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;
}
相關文章
相關標籤/搜索