0-1背包问题:给定n种物品和一背包.物品i的重量是wi, 其价值为ui,背包的容量为C.
问如何选择装入背包的物品,使得装入背包中物品的总价值最大?
分析:
0-1背包是子集合选取问题,一般情况下0-1背包是个NP问题.
第一步 确定解空间:装入哪几种物品
第二步 确定易于搜索的解空间结构:
可以用数组p,w分别表示各个物品价值和重量。
用数组x记录,是否选种物品
第三步 以深度优先的方式搜索解空间,并在搜索的过程中剪枝
我们同样可以使用子集合问题的框架来写我们的代码,和前面子集和数问题相差无几。
问如何选择装入背包的物品,使得装入背包中物品的总价值最大?
分析:
0-1背包是子集合选取问题,一般情况下0-1背包是个NP问题.
第一步 确定解空间:装入哪几种物品
第二步 确定易于搜索的解空间结构:
可以用数组p,w分别表示各个物品价值和重量。
用数组x记录,是否选种物品
第三步 以深度优先的方式搜索解空间,并在搜索的过程中剪枝
我们同样可以使用子集合问题的框架来写我们的代码,和前面子集和数问题相差无几。
- #include<iostream>
- #include<algorithm>
- using namespace std;
- class Knapsack{
- public:
- Knapsack(double *pp,double *ww,int nn,double cc){
- p = pp;
- w = ww;
- n = nn;
- c = cc;
- cw = 0;
- cp = 0;
- bestp = 0;
- x = new int[n];
- cx = new int[n];
- }
- void knapsack(){
- backtrack(0);
- }
- void backtrack(int i){//回溯法
- if(i > n){
- if(cp > bestp){
- bestp = cp;
- for(int i = 0; i < n; i++)
- x[i] = cx[i];
- }
- return;
- }
- if(cw + w[i] <= c){//搜索右子树
- cw += w[i];
- cp += p[i];
- cx[i] = 1;
- backtrack(i+1);
- cw -= w[i];
- cp -= p[i];
- }
- cx[i] = 0;
- backtrack(i+1);//搜索左子树
- }
- void printResult(){
- cout << "可以装入的最大价值为:" << bestp << endl;
- cout << "装入的物品依次为:";
- for(int i = 0; i < n; i++){
- if(x[i] == 1)
- cout << i+1 << " ";
- }
- cout << endl;
- }
- private:
- double *p,*w;
- int n;
- double c;
- double bestp,cp,cw;//最大价值,当前价值,当前重量
- int *x,*cx;
- };
- int main(){
- double p[4] = {9,10,7,4},w[4] = {3,5,2,1};
- Knapsack ks = Knapsack(p,w,4,7);
- ks.knapsack();
- ks.printResult();
- return 0;
- }