一、 问题描述
给定一组物品,每种物品都有自己的重量和价格,在限定的总重量内,我们如何选择,才能使得物品的总价格最高。
具体描述:有N件物品和一个容量为V的背包。第i件物品的重量是w[i],价值是v[i]。求解将哪些物品装入背包可使这些物品的重量总和不超过背包容量,且价值总和最大。
二、 算法描述及代码实现
算法描述:通过问题的详细描述,对于背包问题,本次实验采用回溯算法的思想实现。
在代码实现之前阐述一下回溯算法的思想:
回溯算法也叫试探法,它是一种系统地搜索问题的解的方法。回溯算法的基本思想是:从一条路往前走,能进则进,不能进则退回来,换一条路再试。用回溯算法解决问题的一般步骤为:
1、定义一个解空间,它包含问题的解。
2、利用适于搜索的方法组织解空间。
3、利用深度优先法搜索解空间。
4、利用限界函数避免移动到不可能产生解的子空间。
问题的解空间通常是在搜索问题的解的过程中动态产生的,这是回溯算法的一个重要特性。
编译环境:c++ 编译工具:codeblocks
代码实现:
<span style="font-size:18px;">#include<iostream>
using namespace std;
int n,c,bestp;//物品的个数,背包的容量,最大价值
int p[100],w[100],x[100],bestx[100];//物品的价值,物品的重量,x[i]暂存物品的选中情况,物品的选中情况
void Backtrack(int i,int cp,int cw){//cw当前包内物品重量,cp当前包内物品价值(核心函数)
if(i > n){//结束回溯
if(cp > bestp){
bestp = cp;
for(int i = 0;i < n;i++)
bestx[i] = x[i];
}
}
else
for(int j = 0;j <= 1;j++){
x[i] = j;
if(cw+x[i]*w[i] <= c){
cw += w[i] * x[i];//每个解向量的分量的c与当前的w[i]和前一个解向量分量的cw有关
cp += p[i] * x[i];
Backtrack(i+1,cp,cw);//递归调用
}
}
}
int main() {
int i;
bestp=0;
cout<<"输入物品个数:"<<endl;
cin>>n;
cout<<"输入背包最大容量:"<<endl;
cin>>c;
cout<<"依次输入物品的重量:"<<endl;
for(i=1;i<=n;i++)
cin>>w[i];
cout<<"请依次输入物品的价值:"<<endl;
for(i=1;i<=n;i++)
cin>>p[i];
Backtrack(1,0,0);
cout<<"最大价值为:"<<endl<<bestp<<endl;
cout<<"物品的选中情况依次为(0表示没有被选中,1表示被选中)"<<endl;
for(i=1;i<=n;i++)
cout<<bestx[i];
cout<<endl;
return 0;
}</span>
初始条件:
物品数量n;背包最大容量:c;物品依次的重量:w[i];物品依次的价值p[i]。
博客地址:http://blog.youkuaiyun.com/it_faquir/article/details/50436894
三、 学习该算法心得
回溯算法以“不进则退,能进则进“ 的思想,大大优化了深度优先搜索。无论是本次实验的背包问题还是八皇后问题、装载问题等等都是很好的算法选择。