回溯法求解0-1背包问题
问题描述:略
解题分析:确定约束函数和限界函数
*约束函数:cw(i)+w(i)<=total_weight --重量
*限界函数:B(i) = cv(i)+r(i); --价值
解空间组织:树或图
树结构:子集树、排列树
搜索方式:深度优先
算法的核心:回溯函数&限界函数,其中约束函数没有单独写出来,在代码中有用到
//回溯函数
//每个结点的左右子树都要判断,因为装或不装两种情况都要考虑
void backtrack(int i){
//计算最大上界
bound(i);
if(i>c_num){
//到达叶子结点
bestv = cv;
for(int k=1; k<=c_num; k++){
//把最优解记录下来
best[k] = x[k];
}
return ;
}
if(cw + w[i] <= capacity){
//搜索左子树
cw += w[i];
cv += v[i];
x[i] = 1;
//深度搜索
backtrack(i+1);
cw -= w[i];
cv -= v[i];
x[i] = 0;
}
if(bound(i+1) > bestv)//搜索右子树,必要时剪枝
backtrack(i+1);
}
//计算上界函数
double bound(int i){
//背包剩余重量
double leftw = capacity-cw;
//背包当前价值
double b = cv;
for(int k = i; k<=c_num;k++){
//剩余物品重量、价值分别存在w2、v2数组中
w2[k]=w[k];
v2[k] = v[k];
}
//将剩余物品按单位重量价值排序
knapsack(i);
while(i<=c_num && w2[i]<=leftw){
//将剩余已排好序的物品装入背包
leftw -= w2[i];
b += v2[i];
i++;
}
if(i<= c_num)
b += v2[i]/w2[i] * leftw;
return b;
}
其他部分:
#include "backpack.h"
#include <iostream>
using namespace std;
//声明变量
int c_num; //物品数量
double capacity; //背包容量
double v[100]; //各个物品的价值
double w[100]; //各个物品的重量
double cw = 0.0; //当前背包的重量
double cv = 0.0; //当前背包中物品价值
double bestv = 0.0; //当前最优价值
double perv[100]; //物品按单位重量价值排序
int x[100]; //是否装入,为0或1
int best[100]; //记录最优解,为0或1
double v2[100]; //临时存放各个物品的价值
double w2[100]; //临时存放各个物品的重量
int main(){
init();
backtrack(1);
cout<<"最大价值为:"<<bestv<<endl;
cout<<"需要装入的物品编号是:"<<endl;
for(int i = 1; i<=c_num; i++){
if(best[i])
cout<<i<<" ";
}
cout<<endl;
system("pause");
return 0;
}
//第一步:初始化
void init(){
//输入物品数量n、背包容量c
cout<<"请输入物品数量和背包容量:";
cin>> c_num >> capacity;
for(int i = 1; i<=c_num; i++){
//输入各个物品重量wi、价值vi
cout<<"输入第"<<i<<"个物品重量和价值:";
cin>> w[i]>> v[i];
perv[i] = v[i]/w[i];
w2[i] = v2[i] = 0;
x[i] = 0;
best[i] = 0;
}
}
//第二步:排序【快速排序】
void quicksort(int p, int q, double arr[], double key){
int i ,j;
i = p;
j = q;
if(p>=q)
return ;
while(1){
while(j >= p && arr[j]<key)
j--;
if(j<=i)
break;
swap(i,j,arr);
swap(i,j,w2);
swap(i,j,v2);
while(i<=q && arr[i]>=key)
i++;
if(j<=i)
break;
swap(i,j,arr);
swap(i,j,w2);
swap(i,j,v2);
}
quicksort(p,j-1,arr,arr[p]);
quicksort(j+1,q,arr,arr[j+1]);
}
//交换两元素
void swap(int i,int j,double arr[]){
double t;
t=arr[i];
arr[i]=arr[j];
arr[j]=t;
}
//按单位价值排序
void knapsack(int t)
{
quicksort(t,c_num,perv,perv[t]);
}