回溯法(二)——0-1背包问题

回溯法其实就是暴力,这个题目就是暴力的n层for(2次)循环。

  问题1、给定背包容量w,物品数量n,以及每个物品的重量wi,求背包最多能装多少多重的物品。
  问题2、给定背包容量w,物品数量n,以及每个物品的重量wi、价值vi,求背包最多能装多少价值的物品。
  这是一个基本的0-1背包问题,每个物品有两种状态(0:不装、1:装),总共有n步,所以可以用回溯法来解决,复杂度是O(2^n)。

C++版代码如下
#include <iostream>
#include <math.h>
#include <cstring>
using namespace std;

#define MAXSIZE 256

int maxWeight = -9999;

// 回溯法解决0-1背包问题(其实可以暴力(n层for循环),回溯法也是n层for循环,即复杂度是O(2^n))
void basePackage(int stuff[], int curState, int state, int curWeight, int weight){
    // 如果装满了(其实应该是接近装满了)或者已经“走完”所有物品
    if(curState == state || curWeight == weight){
        if(curWeight > maxWeight)
            maxWeight = curWeight;
        return ;
    }

    // 不装
    basePackage(stuff, curState + 1, state, curWeight + 0, weight);
    // 装
    if(curWeight + stuff[curState] <= weight)
        basePackage(stuff, curState + 1, state, curWeight + stuff[curState], weight);
}

// 回溯法解决0-1背包问题(其实可以暴力(n层for循环),回溯法也是n层for循环,即复杂度是O(2^n))
// 背包升级问题回溯法解决(加入背包的价值)
void secPackage(int weight[], int value[], int curV, int curW, int weightLimit, int curS, int n){
    // 如果背包总重量等于背包限制
    if(curW == weightLimit || curS == n){
        if(curV > maxWeight)
            maxWeight = curV;
        return ;
    }

    // 不装
    secPackage(weight, value, curV, curW, weightLimit, curS + 1, n);
    if(curW + weight[curS] <= weightLimit)
        // 装
        secPackage(weight, value, curV + value[curS], curW + weight[curS], weightLimit, curS + 1, n);
}

int main(int argc, char* argv[]){

    // 总重量,物品个数
    int w, n;
    cin>>w>>n;
    int a[MAXSIZE + 1];
    for(int i = 0; i < n; i++)
        cin>>a[i];
    basePackage(a, 0, n, 0, w);
    cout<<maxWeight<<endl;
    return 0;
}
posted @ 2020-08-11 20:59  程序员曾奈斯  阅读(642)  评论(0编辑  收藏  举报