回溯法其实就是暴力,这个题目就是暴力的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;
}