0-1背包问题(回溯法)
用回溯发实现0-1背包问题,问题描述如下:
item |
weights |
values |
A |
50 |
200 |
B |
30 |
180 |
C |
45 |
225 |
D |
25 |
200 |
E |
5 |
50 |
提示:在使用回溯法解决0-1背包问题时,需要对物品进行一次排序,按照单位质量的价值从大到小进行,本实验由于给定数据,排序算法省略,直接使用排序后的结果
#include <iostream> #include <stdlib.h> using namespace std; #define N 6 int W[N] = {0,5,25,30,45,50}; int P[N] = {0,50,200,180,225,200}; double BOUND(int p,int w,int k,int M)
//计算当前状态可以产生的最大价值 { double b = p; int c = w; for(int i = k+1;i < N; i++) { c = c + W[i]; if(c < M) { b = b + P[i]; } else { return (b + (1-(c - M)/W[i])*P[i]); } } return b; } void BKNAP(int M,int n,int& fw,int& fp,int X[]) { int cw =0 , cp = 0; //临时重量和临时价值 int k = 1;fp = -1; //fp表示当前状态下0-1背包问题的最大值 int Y[N]; Y[0] = 0; while(true) { while(k <= n && cw + W[k] <= M) { cw = cw + W[k]; cp = cp + P[k]; Y[k] = 1; k = k + 1; } if(k > n)
//此时已经得到一个满足条件的结果,所以将Y[]的值赋值给X[] { fp = cp; fw = cw; k = n; for(int i = 1; i <= n; i++) X[i] = Y[i]; } else{ Y[k] = 0; } while(BOUND(cp,cw,k,M) <= fp) //如果当前状态下最大的价值情况都小于 fp ,就没有必要继续下去,回溯到最近没有遍历右孩子的节点去 { while(k != 0 && Y[k] != 1) k = k - 1; if(k == 0) return ; Y[k] = 0; cw = cw - W[k]; cp = cp - P[k]; } k = k+1; } } int main() { int X[N],result_p=0,result_w=0; BKNAP(100,N-1,result_w,result_p,X); cout<<result_w<<" "<<result_p<<endl; cout<<"("; for(int i =1; i< N; i++) { cout<<X[i]<<" "; } cout<<")"; return 0; }
结果输出:

浙公网安备 33010602011771号