我有3个仓库,分别命名为A、B、C,它们的最小订购量不同。每块板的每个订单都有最低成本。考虑到订单总数,我已将这些订单分配到每个仓库的至少一块板中,这样我总是选择成本最低的板。
例如:
Slab for warehouse A :
A_1 = Minimum 400000 lakh order : 59.5 cps
A_2 = Minimum 500000 lakh order : 58.2 cps
A_3 = Minimum 770000 lakh order : 55.7 cps
A_4 = Minimum 1100000 lakh : 53.8 cps
A_5 = Minimum 1500000 lakh : 53.1 cps
Slab for warehouse B :
B_1 = Minimum 500000 lakh order : 63 cps
B_2 = Minimum 800000 lakh order : 59.4 cps
B_3 = Minimum 900000 lakh order : 56.5 cps
B_4 =Minimum 1200000 lakh : 53 cps
B_5 =Minimum 1500000 lakh : 52.5 cps
Slab for warehouse C :
C_1 =Minimum 1650000 lakh order : 54 cps
C_2 =Minimum 2000000 lakh order : 50 cps
如果我得到 300000 个订单,那么我不同仓库的最佳板坯组合将是 可以有不同的情况组合,其中给出 2 种情况的示例
Case 1:
warehouse C : minimum order 2000000 * 50 = 100000000 (if we select C_2)
warehouse B : minimum order 900000 * 56.5 = 50850000 (if we select B_3)
warehouse A : minimum order 100000 * 59.5 = 5950000 (if we select A_1)
(100000000 + 50850000 + 5950000)/3000000 = 52.2666666667
Minimum cost for 300000 will be 52.2666666667
Case 2:
warehouse C : minimum order 2000000 * 50 = 100000000 (if we select C_2)
warehouse B : minimum order 130000 * 63 = 8190000 (if we select B_1)
warehouse A : minimum order 770000 * 55.7 = 42889000 (if we select A_3)
(100000000 + 8190000 + 42889000 )/3000000 =50.3596666667
Minimum cost for 300000 will be 50.3596666667
在上述两种情况下,情况2的成本最小,所以我们将选择情况2作为分配。
这里的订单可以是任何数字,例如 6500000 或 8000000。
我尝试了这个,但输出不正确
slabs_A = [(400000, 59.5), (500000, 58.2), (770000, 55.7), (1100000, 53.8), (1500000, 53.1)]
slabs_B = [(500000, 63), (800000, 59.4), (900000, 56.5), (1200000, 53), (1500000, 52.5)]
slabs_C = [(1650000, 54), (2000000, 50)]
total_orders = 300000
allocation = {}
remaining_orders = total_orders
def get_min_cost_slab(slabs, remaining_orders):
min_cost = float('inf')
selected_slab = None
for order, cost in slabs:
if order <= remaining_orders and cost < min_cost:
min_cost = cost
selected_slab = order, cost
return selected_slab
for slabs, warehouse in zip([slabs_A, slabs_B, slabs_C], ['A', 'B', 'C']):
selected_slab = get_min_cost_slab(slabs, remaining_orders)
if selected_slab:
allocation[(warehouse, selected_slab[0])] = selected_slab[1]
remaining_orders -= selected_slab[0]
min_cost = sum(allocation.values())
print(f"Minimum cost for {total_orders} orders: {min_cost}")
print("Optimal Allocation:")
for (warehouse, slab), quantity in allocation.items():
print(f"Warehouse {warehouse}, Slab {warehouse}_{slab}, Quantity: {quantity}")
预期输出如下
Warehouse A, Slab A_3, Quantity: 770000, cost : 770000 * 55.7 = 42889000
Warehouse B, Slab B_1, Quantity:130000, cost : 130000 * 63 = 8190000
Warehouse C, Slab C_2, Quantity:200000, 2000000 * 50 = 100000000
Total cost : (100000000 + 8190000 + 42889000 )/3000000 =50.3596666667
我知道您正在寻找 Python 解决方案,但由于问题发布几个小时后还没有发布任何解决方案,我将提供 Ruby 版本的解决方案,它可以被视为伪代码,我相信可以轻松地将其转换为 Python .
我们得到以下数据。
total = 3_000_000
warehouses = {
:A => {
:A_1 => { :capacity => 400_000, :cost => 59.5 },
:A_2 => { :capacity => 500_000, :cost => 58.2 },
:A_3 => { :capacity => 770_000, :cost => 55.7 },
:A_4 => { :capacity => 1_100_000, :cost => 53.8 },
:A_5 => { :capacity => 1_500_000, :cost => 53.1 }
},
:B => {
:B_1 => { :capacity => 500_000, :cost => 63.0 },
:B_2 => { :capacity => 800_000, :cost => 59.4 },
:B_3 => { :capacity => 900_000, :cost => 56.5 },
:B_4 => { :capacity => 1_200_000, :cost => 53.0 },
:B_5 => { :capacity => 1_500_000, :cost => 52.5 }
},
:C => {
:C_1 => { :capacity => 1_650_000, :cost => 54.0 },
:C_2 => { :capacity => 2_000_000, :cost => 50.0 }
}
}
可以使用以下 Ruby 方法(我将对其进行解释)。
def minimum_cost_allocation(warehouses, tot)
a = warehouses.map { |k,v| v.to_a }
a.shift
.product(*a)
.select { |arr| sufficient_capacity?(arr, tot) }
.min_by do |combo|
cost(combo.permutation(combo.size).min_by { |perm| cost(perm, tot) }, tot)
end
end
def sufficient_capacity?(arr, total)
arr.sum { |_lbl, h| h[:capacity] } >= tot
end
def cost(arr, tot)
arr.sum do |_lbl,h|
f = [tot, h[:capacity]].min
tot -= f
f * h[:cost]
end
end
我们现在可以计算上述数据的平板的最小成本分配。
minimum_cost_allocation(warehouses, total)
#=> [[:A_1, {:capacity=>400000, :cost=>59.5}],
# [:B_5, {:capacity=>1500000, :cost=>52.5}],
# [:C_2, {:capacity=>2000000, :cost=>50.0}]]
最低成本
cost(minimum_cost_allocation(warehouses, total), total)
#=> 157550000.0
可以根据
minimum_cost_allocation
的返回值和方法 cost
轻松构建所需的结果格式。
参见方法 Array#map、Array#shift、Array#product、Array#select、Enumerable#min_by、Array#permutation、Array#sum 和 Hash#[] .
对于方法
sufficient_capacity?
if
arr1 = [[:A_5, {:capacity=>1500000, :cost=>53.1}],
[:B_5, {:capacity=>1500000, :cost=>52.5}],
[:C_1, {:capacity=>1650000, :cost=>54.0}]]
然后
sufficient_capacity?(arr1, total)
#=> true
但是,如果
arr2 = [[:A_1, {:capacity=> 400000, :cost=>59.5}],
[:B_1, {:capacity=> 500000, :cost=>63.0}],
[:C_1, {:capacity=>1650000, :cost=>54.0}]]
然后
sufficient_capacity?(arr, total)
#=> false
对于方法
cost
,
cost(arr1, total)
#=> 158400000.0
这等于 `53.1 * 1_500_000 + 52.5 * 1_500_000 + 54.0 * 0 = 158_400_000.0
其中 `3_000_000 - 1_500_000 - 1_500_000 = 0
计算步骤如下。
a = warehouses.map { |_k,v| v.to_a }
#=> [[[:A_1, {:capacity=>400000, :cost=>59.5}],
# [:A_2, {:capacity=>500000, :cost=>58.2}],
# [:A_3, {:capacity=>770000, :cost=>55.7}],
# [:A_4, {:capacity=>1100000, :cost=>53.8}],
# [:A_5, {:capacity=>1500000, :cost=>53.1}]],
# [[:B_1, {:capacity=>500000, :cost=>63.0}],
# [:B_2, {:capacity=>800000, :cost=>59.4}],
# [:B_3, {:capacity=>900000, :cost=>56.5}],
# [:B_4, {:capacity=>1200000, :cost=>53.0}],
# [:B_5, {:capacity=>1500000, :cost=>52.5}]],
# [[:C_1, {:capacity=>1650000, :cost=>54.0}],
# [:C_2, {:capacity=>2000000, :cost=>50.0}]]]
b = a.shift
#=> [[:A_1, {:capacity=>400000, :cost=>59.5}],
# ...
# [:A_5, {:capacity=>1500000, :cost=>53.1}]]
a
#=> [[[:B_1, {:capacity=>500000, :cost=>63.0}],
# ...
# [:B_5, {:capacity=>1500000, :cost=>52.5}]],
# [[:C_1, {:capacity=>1650000, :cost=>54.0}],
# [:C_2, {:capacity=>2000000, :cost=>50.0}]]]
c = b.product(*a)
#=> [[[:A_1, {:capacity=>400000, :cost=>59.5}],
# [:B_1, {:capacity=>500000, :cost=>63.0}],
# [:C_1, {:capacity=>1650000, :cost=>54.0}]],
# [[:A_1, {:capacity=>400000, :cost=>59.5}],
# [:B_1, {:capacity=>500000, :cost=>63.0}],
# [:C_2, {:capacity=>2000000, :cost=>50.0}]],
# ...
# [[:A_5, {:capacity=>1500000, :cost=>53.1}],
# [:B_5, {:capacity=>1500000, :cost=>52.5}],
# [:C_1, {:capacity=>1650000, :cost=>54.0}]],
# [[:A_5, {:capacity=>1500000, :cost=>53.1}],
# [:B_5, {:capacity=>1500000, :cost=>52.5}],
# [:C_2, {:capacity=>2000000, :cost=>50.0}]]]
c.size
#=> 50
c
包含所有大小为 3 的数组,其中第一个元素取自 a[0]
,第二个取自 a[1]
,第三个取自 a[2]
。有 b.product(*a).size #=> 50
个元素,等于 a[0].size*a[1].size*a[2].size #=> 5*5*2
。
d = c.select { |arr| sufficient_capacity(arr, tot) }
#=> [[[:A_1, {:capacity=>400000, :cost=>59.5}],
# [:B_2, {:capacity=>800000, :cost=>59.4}],
# [:C_2, {:capacity=>2000000, :cost=>50.0}]],
# ...
# [[:A_5, {:capacity=>1500000, :cost=>53.1}],
# [:B_5, {:capacity=>1500000, :cost=>52.5}],
# [:C_2, {:capacity=>2000000, :cost=>50.0}]]]
d.size
#=> 43
d
从c
(不可行)元素中删除其组合容量小于total
的元素。
我们现在必须检查
3x2 #=> 6
中每个数组的所有 d
排列。对于每个排列perm
,我将首先将库存分配给板坯perm[0]
,然后是perm[1]
,然后是perm[2]
,观察板坯产能。 43*6 #=> 258
因此必须计算组合的成本。
d.min_by do |combo|
best = combo.permutation(combo.size).min_by { |perm| cost(perm, tot) }
puts "for combo = #{combo}\nbest = #{best}"
cst = cost(best, tot)
puts "cost of best = #{cst}"
cst
end
#=> [[:A_1, {:capacity=>400000, :cost=>59.5}],
# [:B_5, {:capacity=>1500000, :cost=>52.5}],
# [:C_2, {:capacity=>2000000, :cost=>50.0}]]
显示以下内容。
for combo = [[:A_1, {:capacity=>400000, :cost=>59.5}],
[:B_2, {:capacity=>800000, :cost=>59.4}],
[:C_2, {:capacity=>2000000, :cost=>50.0}]]
best = [[:B_2, {:capacity=>800000, :cost=>59.4}],
[:C_2, {:capacity=>2000000, :cost=>50.0}],
[:A_1, {:capacity=>400000, :cost=>59.5}]]
cost of best = 159420000.0
for combo = [[:A_1, {:capacity=>400000, :cost=>59.5}],
[:B_3, {:capacity=>900000, :cost=>56.5}],
[:C_2, {:capacity=>2000000, :cost=>50.0}]]
best = [[:B_3, {:capacity=>900000, :cost=>56.5}],
[:C_2, {:capacity=>2000000, :cost=>50.0}],
[:A_1, {:capacity=>400000, :cost=>59.5}]]
cost of best = 156800000.0
...
for combo = [[:A_5, {:capacity=>1500000, :cost=>53.1}],
[:B_5, {:capacity=>1500000, :cost=>52.5}],
[:C_2, {:capacity=>2000000, :cost=>50.0}]]
best = [[:C_2, {:capacity=>2000000, :cost=>50.0}],
[:B_5, {:capacity=>1500000, :cost=>52.5}],
[:A_5, {:capacity=>1500000, :cost=>53.1}]]
cost of best = 152500000.0