自从聪明的你提出了back_forth算法后,从司机到库管到客户到小领导,总之所有人都欢欣鼓舞。因为司机每天只需要跑一单生意,库管不需要考虑装货难度,客户总能在最好的时间收到货物,小领导把村里的年轻人都招来开货车。太好了,这不是提前实现共同富裕奔小康了么。
但是你被你爹打了两巴掌,还被骂败家子。
为啥? 你亏本了。你的方案,是最差的可行解,能不被打么。
这下你回到仓库,坐在马路牙子上思考人生。怎么能降点成本呢?
这时你来到车旁,看见空荡荡的车厢里,只堆了几打豆腐,你拿起一块皮实的老豆腐,忘脑门上一拍,碎泱泱的豆腐渣在脸上分布均匀。
啊!有了,我真他娘的是个天才。
降本增效
你立马叫来经理小经,让他把他们村的司机开除,因为你要让每辆车竟可能多的运输货物,装得慢慢得。
但是怎么装呢? 旁边的小红说,离得近的装一起呗。
好,就选离得近的!
这个方法,就叫最近邻算法。
让一辆车从depot出发,每次选离车辆路线最后的点最近的客户,加入路径。直到下一个点违反了capacity或时间窗约束为止,再生成新的路径。
local function closet(point, node)
local node_time = push_forward(point, node)
return beta[1] * dis(point.id, node) + beta[2] * (node_time - point.fT - nodes[node].stime) + beta[3] * (nodes[node].time2 - point.fT - nodes[node].stime - time(point.id,node))
end
local function isFeasiblePushBack(node)
if dis(route[#route].id,node) and route[#route].fT + nodes[route[#route].id].stime + time(route[#route].id,node) <= nodes[node].time2 then
return route[#route].fW + nodes[node].weight <= vehicle[route.vtp].weight and route[#route].fV + nodes[node].volume <= vehicle[route.vtp].volume
end
end
local function NearestUnroutedNode()
local min, min_v = 0, math.huge
for i=1,#unrouted do
if isFeasiblePushBack(unrouted[i]) then
local cclose = closet(route[#route], unrouted[i])
if cclose < min_v then
min, min_v = i, cclose
end
end
end
local node = unrouted[min]
table.remove(unrouted, min)
return node
end
function NearestInsertion(...)
local solution = Solution:new()
beta, unrouted = {...}, {}
for i=1,#nodes do unrouted[#unrouted+1] = i end
repeat
route = Route:new()
repeat
local next_node = NearestUnroutedNode()
if next_node then
route:push_back(next_node)
else
solution:append(route)
end
until not next_node
until #unrouted == 0
beta, unrouted, route = nil, nil, nil
return solution
end
计算结果如下
现在只需要9辆车,距离成本降到了715.4,牛逼!