0-1背包–回溯算法(C++/C实现)
提示:深度优先搜索(二叉树)理解
#include<stdio.h>
#include<iostream> //c++输入输出流头文件
using namespace std;
int n; //总商品数量
int W; //商品的总容量
int cp=0,cw=0;//当前装入价值;当前装入重量
int bestp=0; //初始化最优解价值
bool x[10],bestx[10]; //可行解存储数组 ;和不断更新的最优解数组
int w[10],v[10]; //第t个商品重量;和第t个价值 存储数组
int bound_func(int i) //计算价值上界
{
int rp=0; //rp:第t+1个商品~第n个商品全部装入的总价值,先初始化为0
while(i<=n) //n为商品总数
{
rp+=v[i];
i++;
}
return rp+cp; //返回当第t个商品不装时,返回前t个商品(不包括第t个)的总价值+剩余的全部商品价值
}
//回溯函数
void func(int t) //t:二叉树层数
{
if(t>n)//更新最优解
{
int i;
for(i=1;i<=n;i++)
{
bestx[i]=x[i]; //将当前最优解赋值给bestx[]数组,以记录当前最优解
}
bestp = cp; //将当前最优解总价值cp传给bestp以存储记录
return ;
}
//判断条件
if(cw+w[t]<=W)//约束条件:先判断加入第t个商品后是否超出总容量W
{
x[t]=1; //将符合约束条件的商品赋值为1
cw+=w[t];
cp+=v[t];
func(t+1);
//回溯时,减去之前加上的重量和价值(之前怎么加的就怎么减回去)
cw-=w[t];
cp-=v[t];
}
/*限界函数:提高回溯效率,优化减少不必要的分支搜索
必须判断当第t个商品不装时,假定剩下的商品全部装入,判断cp+rp
是否"大于"之前的可行解的价值,如果不大于,则没有必要继续向下搜索则回溯
以减少不必要的浪费搜索.*/
if(bound_func(t+1)>bestp)
{
x[t]=0; //将第t个商品不放入,即赋值为0
func(t+1); //继续循环右分支
}
}
void in_func()
{
cout<<"请输入商品的总个数:"; //输入商品总个数
cin>>n;
cout<<"请输入存储商品的总容量:"; //输入存储商品的总容量
cin>>W;
cout<<"请分别输入商品的重量和价值:";
for(int i=1;i<=n;i++) //输入(重量+空格+价值)循环n次输入
{
cin>>w[i]>>v[i];
}
}
void put_func() //输出函数
{
cout<<"放入购物车的物品最大价值为:"<<bestp<<endl;
cout<<"最优解为:";
for(int i=1;i<=n;i++)
{
if(bestx[i]==1)
cout<<i<<" ";
}
cout<<endl; //相当于回车
}
main()
{
in_func();//输入函数
func(1); //处理
put_func(); //输出函数
}
结果: