回溯法求最优装载问题

有一批集装箱要装上一艘载重量为c的轮船。其中集装箱i的重量为wi。最优装载问题要求确定在装载体积不受限制的情况下,将尽可能少的集装箱装上轮船。

例如:n=5,W=10,w={5,2,6,4,3}
装载方案:(1,1,0,0,1) (0,0,1,1,0)
因此最优装载方案是第3、4个集装箱

问题表示:全局变量

int w[]={0,5,2,6,4,3}; 最前面的0不表示
int n=5,W=10 也就是有五个集装箱,轮船的最大载重量为10

如果选择这个箱子就是1,不选择这个箱子就是0, 因此解向量的表示

int maxW ; //存放最优解的总重量,初始值是0
int x[MAIN];//存放最优解向量,初始值是0,也就是取不取这个箱子
int mainNum=99999;//存放最优解的集装箱个数,初值为最大值

求解算法:

void dfs(int num, int tw, int rw, int op[], int i)
num :表示选择集装箱的个数
tw:表示选择的集装箱的重量之和
rw:剩余集装箱的重量和
op:表示一个解,即一个选择方案
i:表示考虑的集装箱i

对于void dfs(int num, int tw, int rw, int op[], int i)的理解以及应用:

对于第i层的某个结点,对应的调用状态是dfs(num,tw.rw,op,i+1)
(1)如果要选择第i个结点,也就是第i个集装箱,
op[i]=1,num=num+1,tw=tw+w[i],rw=rw-w[i],
之后转到下一个状态:dfs(num,tw,rw,op,i+1)
该决策对应左分支,也就是选择这一结点
(2)如果不选择第i个结点
op[i]=0,num不变,tw不变,rw=rw-w[i],
之后转到下一个状态:dfs(num,tw,rw,op,i+1)
该决策对应右分支,也就是不选择这一结点

剪枝方式:

左剪枝:
tw+w[i]<=W 则扩展,否则不扩展

右剪枝:
tw+rw-w[i]>=W则扩展,否则不扩展
也就是:如果所有集装箱的重量之和减去当前结点i的重量如果比船的最大装载量大,就扩展这个右分支,否则根本不用扩展
再优化一下也就是:
tw+rw-w[i]>maxW则扩展,否则不扩展

猜你喜欢

转载自blog.csdn.net/qq_46161529/article/details/122093784
今日推荐