背包问题的总结,包含了基本背包,完全背包,多重背包,以及各问题的线性空间复杂度/二维空间复杂度解法。acwing有一些比较基础的题可以进行相关测试。

基本背包问题

01背包平方空间复杂度

int pack_01_vn(const vector<int> &costs, const vector<int> &values, int maxCost){
    vector<vector<int>> dp(costs.size()+1,vector<int>(maxCost+1,0));
    for (int i = 1; i <= costs.size(); ++i) {
        int objidx = i-1;
        for (int j = maxCost; j >= 0; j--) {
            if(j >= costs[objidx]){
                dp[i][j]=max(dp[i-1][j-costs[objidx]]+values[objidx],dp[i-1][j]);
            }else{
                dp[i][j]= dp[i-1][j];
            }
        }
    }
    return dp.back().back();
}

01背包线性空间复杂度

int pack_01_v(const vector<int> &costs, const vector<int> &values, int maxCost){
    vector<int> dp(maxCost+1,0);
    int nType = costs.size();
    for (int i = 0; i < nType; ++i) {
        for (int j = maxCost; j >= costs[i]; j--) {
            dp[j] = max(dp[j],dp[j-costs[i]]+values[i]);
        }
    }
    return dp[maxCost];
}

完全背包

完全背包平方空间复杂度

int pack_comp_vn(const vector<int> &costs, const vector<int> &values, int maxCost){
    vector<vector<int>> dp(costs.size()+2,vector<int>(maxCost+1,0));
    for (int i = 1; i <= costs.size()+1; ++i) {
        int costi = i-2>=0?costs[i-2]:0;
        int valuei = i-2>=0?values[i-2]:0;
        for (int j = 0; j <= maxCost; j++) {
            if(j >= costi){
                dp[i][j]=max(dp[i][j-costi]+valuei,dp[i-1][j]);
            }else{
                dp[i][j]= dp[i-1][j];
            }
        }
    }
    return dp.back().back();
}

完全背包线性空间复杂度

int pack_comp_v(const vector<int> &costs, const vector<int> &values, int maxCost){
    vector<int> dp(maxCost+1,0);
    int nType = costs.size();
    for (int i = 0; i < nType; ++i) {
        int costi = i-1>=0?costs[i-1]:0;
        int valuei =  i-1>=0?values[i-1]:0;
        for (int j = 0; j <= maxCost; j++) {
            if(j - costi >= 0)
                dp[j] = max(dp[j],dp[j-costi]+valuei);
        }
    }
    return dp[maxCost];
}

多重背包

多重背包线性空间复杂度——二进制拆分

int pack_multi_v_bin(const vector<int> &costs, const vector<int> &values, const vector<int> &numbers, int maxCost){   
    vector<int> dp(maxCost+1,0);    
    int nType = costs.size();    
    for (int i = 0; i < nType; ++i) {       
        int base = 1;        
        int goodsLeft = numbers[i];        
        while(goodsLeft > 0){            
            int currN = base;           
            if(currN > goodsLeft) 
                currN = goodsLeft;            
            int currCost = currN*costs[i];            
            int currValue = currN*values[i];            
            for (int j = maxCost; j >= currCost; j--) {                
                dp[j] = max(dp[j],dp[j-currCost]+currValue);           
            }           
            goodsLeft -= currN;           
            base *= 2;       
        }    
    }   
    return dp[maxCost];
}

多重背包线性空间复杂度——单调队列

int pack_multi_v_queue(const vector<int> &costs, const vector<int> &values, const vector<int> &nums,int maxCost){
    vector<int> dp_prev(maxCost+1,0);
    vector<int> monotone_queue(maxCost+1,0);
    vector<int> dp(maxCost+1,0);
    for (int i = 0; i < costs.size(); ++i) {
        dp_prev=dp;
        int volume=costs[i], value = values[i], number=nums[i];
        for (int j = 0; j < volume; ++j) {
            int head = 0, tail = -1;
            for (int k = j; k <= maxCost; k += volume) {
                if (head <= tail && (k - monotone_queue[head]) / volume > number)
                    head++;
                if (head <= tail)
                    dp[k] = max(dp[k], dp_prev[monotone_queue[head]] + (k - monotone_queue[head]) / volume * value);

                while (head <= tail && dp_prev[monotone_queue[tail]] - (monotone_queue[tail] - j) / volume * value<= dp_prev[k] - (k - j) / volume * value) {
                    --tail;
                }
                monotone_queue[++tail] = k;
            }
        }
    }
    return dp[maxCost];
}

标签: none

添加新评论