回溯法求0/1背包问题

时间:2021-01-24 04:20:11

回溯法求0/1背包问题

给定n件物品和一个容量为c的背包,物品的重量为Wi,其价值为Vi,0/1背包问题是如何选择背包的物品,其中背包的物品是不可分割的,怎样使得背包中的物品价值最大?

#include"stdio.h"
#include"stdlib.h"
int num;//物品数量
double capability;//背包容量
double value[100];//每个物品价值
double weight[100];//每一个物品的重量
double currentWeight=0.0;//当前背包重量
double currentValue=0.0;//当前背包中物品价值
double bestValue=0.0;//当前最优价值
double valuePerThing[100];//单位物品价值
int order[100];//物品编号
int put[100]={0};//装入的物品
int savePut[100]={0};//保存最优值的设置
void sort(){//排序每件物品的单位价值
int i,j;
int tempOrder=0;
double temp=0.0;

for(i=1;i<=num;i++)
valuePerThing[i]=value[i]/weight[i];
for(i=1;i<=num-1;i++)
for(j=i+1;j<=num;j++){
if(valuePerThing[i]<valuePerThing[j]){
temp=valuePerThing[i];
valuePerThing[i]=valuePerThing[j];
valuePerThing[j]=temp;
tempOrder=order[i];
order[i]=order[j];
order[j]=tempOrder;
temp=value[i];
value[i]=value[j];
value[j]=temp;
temp=weight[i];
weight[i]=weight[j];
weight[j]=temp;

}
}
}


double bound(int i){//确定 上届
double leftWeight=capability=currentWeight;
double b=currentValue;
while(i<=num&&weight[i]<=leftWeight){
leftWeight-=weight[i];
b+=value[i];
i++;
}
if(i<=num)
b+=value[i]/weight[i]*leftWeight;
return b;
}
void backtrack(int i){//回溯过程函数
if(i>num){
if(bestValue<currentValue){
bestValue=currentValue;
for(int j=0;j<num;j++){
savePut[j]=put[j];
}
}
return;
}
if(currentWeight+weight[i]<=capability){
currentWeight+=weight[i];
currentValue+=value[i];
put[i]=1;
backtrack(i+1);
put[i]=0;
currentWeight-=weight[i];
currentValue-=value[i];

}else{

backtrack(i+1);
}
if(bound(i+1)>bestValue)
backtrack(i+1);
}
int main(){//主函数
int i;
printf("请输入物品的数量和容量");
scanf("%d%lf",&num,&capability);
printf("请输入物品的重量和价值\n");
for(i=1;i<=num;i++){
printf("第%d个物品的重量:",i);
scanf("%lf",&weight[i]);
printf("价值是:");
scanf("%lf",&value[i]);
order[i]=i;
}

sort();
backtrack(1);
printf("最有价值为:%lf\n",bestValue);
printf("需要装入的物品编号为:");
for(i=1;i<=num;i++){
if(savePut[i]==1){
printf(" %d ",order[i]);

}
}
printf("\n");
system("PAUSE");
return 0;
}