最优装载问题 回溯算法

#include <iostream>
using namespace std;
const int N=5;
const int C=4;
/*问题描述:
n个物品 重量分别为w[1] w[2]...w[n]
放入一个容量为c的背包里
求可以取得的最大重量。
*/
class maxLoading
{
private:
int n;//包个数
int *w;//包重量数组
int c;//最大容量
int maxW;//记录当前最大装载量
int curW;//记录当前装载量
int r; //改进版需要的 记录如果不要当前包 后面所有包的和重量
int *bestX;//记录最优解向量
int *x; //每次的解向量
public:
maxLoading(int *ww,int nn,int cc);
void backTrack(int i);
void backTrack2(int);//改进版
void result()const;
~maxLoading()
{
   delete [n+1]w;
   delete [] bestX;
   delete [] x;
}
};
maxLoading::maxLoading(int *ww,int nn,int cc)
{
   n=nn;
   w=new int[nn+1];
   for(int i=1;i<=nn;i++)w[i]=ww[i];
   c=cc;
   curW=0;
   maxW=0;
   r=0;
   for(i=1;i<=n;i++)r+=w[i];
   bestX=new int[n+1];
   x=new int[n+1];
}
void maxLoading::result()const
{
   cout<<"最大装载量:"<<maxW;
   cout<<"解向量:";
    for(int i=1;i<=n;i++)
     cout<<bestX[i];
}
/*
算法描述:
逻辑上是一个二叉树的结构,此函数处理第i个包,左孩子代表取第i个包 右孩子代表不取
按深度优先遍历二叉树。虽然有的子树访问不到,但时间复杂度为O(2^n)
*/
void maxLoading::backTrack(int i)
{
         if(i>n)//终止条件,i到了第n+1层,说明已经过了叶子 得到一个可行解
   {
    if(curW>maxW)
    {
     maxW=curW; //如果得到的可行解比以前的任何可行解都大,则把它当作最优解
     for(int j=1;j<=n;j++)
      bestX[j]=x[j];
    }             

   }
   else//还没有到终止条件时,则试试往左,行的话就往左,否则直接往右
    //加上和不加都试试,加上超过了容量就不加
   {
    if(curW+w[i]<=c)//如果当前值加上第i个包的重量也没有超过容量 就往左,即加上这个包。递归
    {
     x[i]=1;
     curW+=w[i];
     backTrack(i+1);
     curW-=w[i];
    }
    x[i]=0;
    backTrack(i+1); //然后往右。
   }
}
/*
缺点是只能截断往左的路径,往右的路径却都不能截断
当前值加上第i个包的重量也没有超过容量 就加上,否则处理下一个,但是否有必要处理
如果后面的所有包都加上 也没有现在已经取到的最优解大 那么就没有必要往下处理了,即截断了右子树
*/  

//改进版:
void maxLoading::backTrack2(int i)
{
    if(i>n)//终止条件
{
   if(curW>maxW)//其实此时curW肯定大于maxW因为在进入最后一个右子树的时候曾经验证过
                         //curW+0〉maxW
   {
    maxW=curW;
    for(int j=1;j<=n;j++)
      bestX[j]=x[j];
   }
   return;
}
r-=w[i]; //当前处理的第i个包 r是i个之后所有包的重量和,所以深入一层之后要减去此包重量
if(curW+w[i]<=c)
{
   x[i]=1;
   curW+=w[i];
   backTrack2(i+1);
   curW-=w[i];
}
if(curW+r>maxW)
{
   x[i]=0;
   backTrack2(i+1);
  
}
r+=w[i]; //处理完右子树 回上一层时要加上这层的重量。
}
int main()
{
int *w=new int[N+1];
cout<<"输入"<<N<<"个质量数:"<<endl;
for(int i=1;i<=N;i++)cin>>w[i];
    
maxLoading m(w,N,C);
m.backTrack2(1);
m.result();
delete []w;
return 1;
}

    原文作者:回溯法
    原文地址: https://blog.csdn.net/longzuo/article/details/45025769
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞