回溯法解最优装载问题

//再来学习一下回溯法
//一般解题步骤分为三步
//一:针对所给问题,定义问题的解空间
//二:确定易于搜索的解空间结构(一般为子集树或者排列树)
//三:以深度优先的方式搜索解空间,并且在搜索过程中用减枝函数避免无效搜索
//其中子集树就是选一部分,比如0-1背包问题,装载问题,
//而排列树就是选所有,只是顺序不一样,例如旅行商(邮递员)问题


//下面是装载问题的解法
//已知n个集装箱,轮船载重量为c,集装箱i的重量为Wi,要求是在不超重的情况下,
//装尽可能多数量的集装箱

#define NUM 100
int n;  //集装箱数量
int c;  //轮船载重量
int w[NUM]; //集装箱重量
int x[NUM]; //当前搜索的解向量
int r;  //剩余集装箱重量
int cw; //当前轮船载重量
int bestw;  //最优载重
int bestx[NUM]; //最优解向量

void init()
{
    bestw=0;
    for(int i=1;i<=n;i++)
    {
        cin>>w[i];
        r+=w[i];
    }
}

//形参代表搜索第t层节点,从1开始
void BackTrack(int t)
{
    //到达叶子节点
    if(t>n)
    {
        for(int i=1;i<=n;i++)
        {
            bestx[i]=x[i];
        }
        bestw=cw;
    }
    else
    {
        r-=w[t];    //更新剩余集装箱重量
        //判断是否可以向左
        //没有超出载重量
        if(cw+w[t]<=c) 
        {
            x[t]=1;
            cw+=w[t];
            BackTrack(t+1);
            cw-=w[t];   //返回时要将当前载重量还原
        }
        //判断是否可以向右
        //如果当前载重量加上剩余集装箱的重量没有超过前一个最优装载量的话就不用考虑了
        //此处即为剪枝函数
        if(cw+r>bestw)      
        {
            x[t]=0;     //1代表选上,0代表不选
            BackTrack(t+1);
        }
        r+=w[t];    //返回时还原剩余集装箱重量
    }
}



你可能感兴趣的:(回溯法解最优装载问题)