回溯法-----最优装载问题

回溯法有“通用的解题法”之称,可以系统的搜索一个问题的所有解或任一解。它在问题的解空间中按深度优先策略,从根节点出发,搜索解空间树。算法搜索至解空间树的任一节点时,先判断该节点是否包含问题的解,如果肯定不包含则跳过对以该节点为根的子树的搜索,回到其父节点回溯。否则,进入该子树,继续按深度优先策略搜索。

与蛮力算法(穷举法)不同在于:回溯算法多了“观望”,可行则前进,不可行则回溯

利用回溯法解问题时一般按以下三步骤:

(1)定义搜索问题的解向量和每个分量的取值范围,解向量是<x1,x2...xn>,确定xi的取值集合,i=1,2....

(2)在<x1,x2...xk-1>确定如何计算xk的取值集合Sk

(3)确定节点儿子的排列规则

(4)判断是否满足多米诺性质

(5)确定每个节点的约束条件

(6)确定搜索策略(深度优先?宽度优先?或者其他)

(7)确定存储搜索路径的数据结构

最优装载问题的回溯算法实现:

 

二、回溯法应用——装载问题

 

一批集装箱共n个要装上2艘载重量分别为c1和c2的轮船,其中集装箱i的重量为Wi且W1+W2+……+Wn<=c1+c2;试确定一个合理的装载方案使这n个集装箱装上这两艘轮船。

#include<stdlib.h>
#include<stdio.h>
#include<iostream>

using namespace std;

typedef int Status;
typedef int Type;

int n = 0;    //集装箱数
Type *x = (Type*)malloc((50)*sizeof(Type));//当前解
Type *bestx = (Type*)malloc((50)*sizeof(Type));//当前最优解
Type c = 0,   //第一艘轮船的载重量
cw = 0,       //当前载重量
bestw = 0,    //当前最优载重量
r = 0,
*w = (Type*)malloc((50)*sizeof(Type));    //集装箱重量数组

int Backtrack(int i)//搜索第i层节点
{
    int j_index;
    /*如果到达叶结点,则判断当前的cw,如果比前面得到的最优解bestw 好,则替换原最优
    解。*/
    if (i>n)
    {
        if (cw>bestw)
        {
            for (j_index = 1; j_index <= n; j_index++)
                bestx[j_index] = x[j_index]; bestw = cw;
        }
        return 1;
    }

    //搜索子树
    r -= w[i];
    if (cw + w[i] <= c)//搜索左子树,如果当前剩余空间可以放下当前物品也就是,cw + w[ i ] <= c
    {
        x[i] = 1;
        cw += w[i];//把当前载重 cw += w[ i ]
        Backtrack(i + 1);//递归访问其左子树,Backtrack( i + 1 )
        cw -= w[i];//访问结束,回到调用点, cw - = w[ i ]
    }

    if (cw + r>bestw)//搜索x[i]的右子树,试下不装x[i]是否可行
    {
        x[i] = 0;
        Backtrack(i + 1);
    }
    r += w[i];//走到这里,x[i]不装的路径已经试完,应该试下x[i]节点上面,x[i-1]不装的路径
}
Type* Initiate()
{
    int index = 1;
    printf("输入集装箱个数:");
    scanf("%d", &n);
    printf("输入轮船载重量:");
    scanf("%d", &c);

    while (index <= n)//数组从1号单元开始存储
    {
        printf("输入集装箱%d 的重量:", index);
        scanf("%d", &w[index]);
        index++;
    }

    bestw = 0;
    cw = 0;
    r = 0;
    for (index = 1; index <= n; index++)
        r += w[index]; //初始时r 为全体物品的重量和
    printf("n=%d c=%d cw=%d bestw=%d r=%d\n", n, c, cw, bestw, r);

    for (index = 1; index <= n; index++)
    {
        printf("w[%d]=%d          ", index, w[index]);
    }
    printf("\n");
    return w;
}
int main()
{
    int i;
    Initiate();
    //计算最优载重量
    Backtrack(1);
    for (i = 1; i <= n; i++)
    {
        printf("%d        ", w[i]);
        printf("%d\n", bestx[i]);
    }
    return bestw;
}

 

转载必须注明出处

 

 

 

  • 3
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
最优装载问题是指在给定一些货物和一些集装箱的容量限制下,如何选择并装载货物使得装载的总重量最大。这是一个经典的组合优化问题,可以使用回溯法进行求解。 回溯法的基本思想是将问题的解空间表示成一个树形结构,从根节点开始递归搜索所有可能的解,当搜索到叶子节点时,判断该叶子节点是否满足问题的约束条件,如果满足则记录该解,并回溯到上一层继续搜索,如果不满足则直接回溯到上一层。 具体来说,对于最优装载问题,可以将每个货物看作一个节点,每个节点有两种状态,即选中和不选中。从根节点开始,依次选择每个节点的状态,计算当前装载的总重量,如果超出了集装箱的容量限制则回溯到上一层,否则继续递归搜索下一层节点。当搜索到叶子节点时,记录当前的最优解,并回溯到上一层继续搜索。最终,所有可能的解都会被搜索到,从中选取最优解即可。 需要注意的是,使用回溯法求解最优装载问题的时间复杂度很高,因为需要搜索所有可能的解。为了提高效率,可以使用剪枝策略,即在搜索过程中根据当前装载的总重量和集装箱的容量限制,预测当前节点的子树中可能出现的最大总重量,如果该值小于当前的最优解,则可以剪枝,直接回溯到上一层。这样可以避免搜索无用的子树,减少搜索时间。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值