问题:0/1背包问题
例子:weight数组代表物品重量,value数组代表物品价值,M代表背包容量。背包是按单位价值递减的顺序排列的,即value[i]/weight[i]>value[i-1]/weight[i-1].
const int weight[Max]={1,11,21,23,33,43,45,55};const int value[Max]={11,21,31,33,43,53,55,65};intM=110;迭代法的回溯分析:回溯法可以通过限界函数做剪枝处理。搜素的约束函数是总重量<=背包容量M.下面通过贪心算法确定限界函数,当前面k-1个物品已经做好装包决策,可能达到的最大效益值是该上界函数。// BackTrace_0_1backpack.cpp : 定义控制台应用程序的入口点。
//回溯法解决0/1背包问题;
#include "stdafx.h"
#include
#include
#include
using namespace std;
const int Max=8;
const int weight[Max]={1,11,21,23,33,43,45,55};
const int value[Max]={11,21,31,33,43,53,55,65};
//如果搜素算法在求解该节点之前已经知道目前的最优解大于这个界值的效益,就没有必要接着搜素下去。
//前k件物品是否装已经确定,还剩k+1,...,Max-1件未装
double BoundF(int cp, int cw, int k, int M)
{
double b=cp, c=cw;
int i;
for(i=k+1;i BackKnap(int M,double & fp)
{
vector X(Max),Y(Max);
int cw,cp,k;
fp=-1;//当前搜素的最优解,初始时设为-1
cw=cp=k=0;
do{
while(k=Max)
{
fp=cp;//
k=Max-1;//搜索到一个当前最好的结果时,保存在X中
for(int i=0;i=0&&Y[k]!=1)//回溯到第一个非零的节点
k--;
if(k<0) return X;//如果回溯到顶,说明已经遍历完所有结果
//下面是已经找到了第一个Y[k]=1的节点,将其设为0,更新cw,cp.再从该节点开始往下搜索
Y[k]=0;
cw=cw-weight[k];
cp=cp-value[k];
}
k++;
}while(1);
}
void show(int i)
{
cout
double fp;
X=BackKnap(M,fp);
for_each(X.begin(),X.end(),show);
cout<
递归的回溯没有考虑利用限界函数剪枝,仅根据约束条件遍历回溯。// Back_trace_0_1_backKnap.cpp : 定义控制台应用程序的入口点。
//
// BackTrace_0_1backpack.cpp : 定义控制台应用程序的入口点。
//回溯法解决0/1背包问题;
#include "stdafx.h"
#include
#include
#include
using namespace std;
const int Max=8;
const int weight[Max]={1,11,21,23,33,43,45,55};
const int value[Max]={11,21,31,33,43,53,55,65};
int M=110;//背包容量
int bestp=-1;//最优解
int bestx[Max];
vector x(Max);
// 已对前i-1个物品是否装入做好决策,对第i个物品装入的算法
void Backtrack(int i,int cp, int cw)//cp,cw是当前的背包内物品的重量和价值
{
int j;
if(i>=Max)//到达一个叶节点,说明得到一个可行解
{
if(cp>bestp)//如果这个解能达到更好的效益值,更新解的结果
{
bestp=cp;
for(i=0;i