回溯法0-1背包问题
本文以 http://blog.sina.com.cn/s/blog_690e57390100khgl.html 为主题编写的回溯0-1背包问题
1、问题描述
物品总数量为n,背包容量为v,物品价值分别为value(……),物品重量为weight(…….),求如何存放物品使背包价值最大。
2、回溯算法思路
- 初始化数据后,我们先从第一个物品存入到背包中,
- 判断物品是否已经使用完毕。如何使用完,判断是否当前价值量大于原有最大价值量,如果大于将最大价值量替换,标记放入的物品,否则不做修改
- 随后,我们判断是否物品存入超出了背包总容积,如果没有将背包现
在容积以及价值量相加,设置标志已放入背包,保存,随后将下一个背包存放测试,跳转到2 - 第3步内为一直测试二叉树的左子树,当到达最底部左子树后,回溯到上一结点,现存容积与价值量减去当前结点重量与价值量,进行该结点右子树循环查找,直到第2步返回
- 回溯结束,跳转到主函数输出结果
以下为VC6.0 下所写代码
#include "stdafx.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
typedef struct {
int number; //物品总数量
int volume; //背吧容量
int curValue; //背包现存价值
int curVolume; //背包现存容量
int* curBackpack; //背包内存放物品数组,curPackage[i] = 1; 为已 经放入背包中
// = 0; 为未放入背包中
int maxValue; //背包最大价值量
int* lastBackpack;//最优解背包内物品
int* goodsValue; //物品价值数组
int* goodsWeight; //物品重量数组
}Backpack;
Backpack bp;
void initBackpack(int v, int n){
bp.number = n;
bp.volume = v;
bp.curValue = 0;
bp.curVolume = 0;
bp.maxValue = 0;
bp.goodsValue = (int*)malloc(bp.number * sizeof(int));
memset(bp.goodsValue, 0, bp.number * (sizeof(int)));
bp.goodsWeight = (int*)malloc(bp.number * sizeof(int));
memset(bp.goodsWeight, 0, bp.number * (sizeof(int)));
bp.curBackpack = (int*)malloc(bp.number * sizeof(int));
memset(bp.curBackpack, 0, bp.number * (sizeof(int)));
bp.lastBackpack = (int*)malloc(bp.number * sizeof(int));
memset(bp.lastBackpack, 0, bp.number * (sizeof(int)));
for(int j=0;j < bp.number;j++){
printf("请输入第%d个物品价值:",(j+1));
scanf("%d",&bp.goodsValue[j]);
printf("请输入第%d个物品重量:",(j+1));
scanf("%d",&bp.goodsWeight[j]);
}
}
void backTrace(int position){
if((position+1) > bp.number){
//当物品全部测试后,查看最大价值量,如何新的价值量大于上一次价值量
//替换掉,并记忆存放的物品
if(bp.curValue > bp.maxValue){
bp.maxValue = bp.curValue;
for(int i=0;i < bp.number;i++){
bp.lastBackpack[i] = bp.curBackpack[i];
}
}
return;
}
//需要通过二叉树图一步步了解回溯
if((bp.curVolume + bp.goodsWeight[position]) <= bp.volume){
bp.curVolume += bp.goodsWeight[position];
bp.curValue += bp.goodsValue[position];
bp.curBackpack[position] = 1;
backTrace(position+1);
bp.curVolume -= bp.goodsWeight[position];
bp.curValue -= bp.goodsValue[position];
}
bp.curBackpack[position] = 0;
backTrace(position+1);
}
int main(int argc, char* argv[])
{
int volume,number;
printf("请输入背包容量:");
scanf("%d",&volume);
printf("请输入物品数量:");
scanf("%d",&number);
initBackpack(volume, number);
backTrace(0);
if(bp.maxValue != 0){
printf("背包最大价值数为:%d\n",bp.maxValue);
printf("背包内存放的物品为:");
for(int i=0;i < bp.number;i++){
if(bp.lastBackpack[i] == 1){
printf("第%d个物品;",(i+1));
}
}
printf("\n");
}else{
printf("\n无最优解\n");
}
return 0;
}
声明
本文以开头博客为参考,将算法进行重新编写了下,如有异议可留言。本文为作者第一篇博文,如有错误之处,请留言指出,谢谢!