计算满足BFS搜索顺序和运输批量的最小运输数量

最近在项目中遇到一个问题,可以用图来表示,我觉得有点意思。我将它抽象为了类似leetcode的题目,放在这里,看大家有没有思路。

问题描述

解决的是在分销网络中,当终端节点产生需求时,如何按照指定规则从上游节点补货来满足终端需求。规则包括1)按BFS的搜索顺序搜索上游节点的库存以满足终端需求,2)当一个节点有多个上游时,则按优先级的顺序搜索,3)两点之间的运输数量满足运输批量要求,4)货物只能沿着线路运输,5)每个节点只能被搜索一次,6)在满足以上规则的基础上最小化运输到需求节点的数量以满足需求。

为方便描述,用一个有向图表示前4个规则。如图1,图中有5个节点,4条有向边。其中节点1需要1000个单位的商品,即缺货1000,节点2有库存商品100个单位,节点3有库存商品500个单位、节点4有库存商品500个单位、节点5有库存商品500个单位。节点1有两个上游,对应图中节点1有两个入边(2,1)和(2,500),每条边上有两个数字,如(2,1)上的数字(1,500),第一个数字1代表优先级,数字越小越优先,第二个数字500表示运输批量。边(2,1)的优先级为1,(3,1)的优先级为2,那么当节点1缺货时,其将优先从节点2补货。运输批量500指,当节点2向节点1补货时,其补货的数量应为500的整数倍。
图1:问题描述示例

输入和输出范例

输入三个整数数组demand, stocks, lines。
 示例:

  • 输入数据:
    demand: [1, 1000]
    stocks: [[2, 100], [3,500], [4, 500], [5, 500]]
    lines: [[2, 1, 1, 500],
    [3, 1, 2, 500],
    [4, 2, 1, 100],
    [5,3,1,200]]
    图1 示例
    用一个图表示上述数据,图中有5个节点,4条线路。节点1有一个需求,节点2-5均有库存(图中的供应)。demand是一个1x2的数组,表示节点demand[0]的需求数量为demand[1],比如[1, 1000]表示节点1的需求数量为1000。
    stocks是二维数组,表示各个节点的库存的数量,比如例子中表示节点2的库存数量为100,节点3的库存数量为500,节点4的库存数量为500,节点5的库存数量为500。
    lines是一个二维数组,每个元素表示一条线路,记录了每条线路的起点、终点、优先级、运输批量。如[3, 1, 2, 500]表示线路的起点是3,终点是1,优先级是2,运输批量为500。

  • 输出数据:[[4, 2, 500], [3,1,500], [2,1,500]]
    表示节点4向节点2运输400个单位的商品,节点3向节点1运输500个单位的商品,节点2向节点1运输500个单位的商品。
    推导过程:(搜索节点的顺序为BFS的搜索顺序,用队列queue记录需要搜索的节点。)

    • 初始状态,queue=[1]
    • step 1: 移除队列中的第一个节点1。节点1需要1000个单位的商品,节点1本地没有库存,节点1的入弧有(2, 1, 1, 500)和节点(3, 1, 2, 500),其中弧(2, 1, 1, 500)的优先级更高(优先级数字越小,优先级越高),将节点2和3加入队列中。【queue=[2,3]】
    • step 2:移除队列中的第一个节点2,节点2的库存为100,但是弧(2, 1, 1, 500)的运输批量为500,因此无法向下运输。此时,需求量仍然为1000。节点2的入弧有(4,2,1,100),将节点4加入队列中。【queue=[3,4]】
    • step 3: 移除队列中的第一个节点3,节点3的库存为500,弧(3, 1, 2, 500)的运输批量为500,因此刚好沿着弧(3, 1, 2, 500)向节点1运输500个单位的商品。此时,需求数量减少为500。节点3的入弧有(5,3,1,100),将节点5加入队列中。【queue=[4,5]】
    • step 4: 移除队列中的第一个节点4,节点4有库存500个单位,此时需求数量为500。节点4的下游节点2有100个单位商品的库存未使用,弧(4, 2, 1, 100)的运输批量为100,因此节点4只需要沿着弧(4, 2, 1, 100)运输400个单位的商品。此时节点2共有库存500个单位,沿着弧(2, 1, 1, 500)向节点1运输500个单位的商品。此时需求被完全满足。退出。
    • :为方便解释对结果的要求,用上述步骤解释了计算过程。你不需要按照这个步骤实现。

2 例子

2.1 例1:阐述优先级

图2 例1阐述优先级
输入:demands: [[1, 1000]];
stocks: [[2, 3200], [3,1050]]
lines: [[2, 1, 1, 1000],
[3, 1, 2, 1000]]
输出:[[2, 1, 1000]]
解释:弧(2,1,1,1000)的优先级高,且节点2的库存数量超过弧的(2,1,1,1000)的运输批量,因此优先使用节点2的库存。

2.2 例2:阐述运输批量

例2阐述优先级
输入:demands: [[1, 1050]];
stocks: [[2, 900], [3,2000]]
lines: [[2, 1, 1, 1000],
[3, 1, 2, 1000]]
输出:[[3, 1, 2000]]
解释:弧(2,1,1,1000)的优先级高,但节点2的库存数量小于弧(2,1,1,1000)的运输批量,因此不使用节点2的库存。
节点1的需求量为1050,节点3的库存数量为2000,但弧(2,1,1,1000)的运输批量为1000,因此需要从节点3向节点1运输2000个单位的商品。

2.3 例3

例3
输入:demands: [[1, 5000]];
stocks: [[2, 1200], [3, 2005], [4, 500], [5, 1200], [6, 1300]]
lines: [[2, 1, 1, 1000],
[3, 1, 2, 1000],
[6, 1, 3, 1000],
[4, 3, 1, 500],
[5, 3, 2, 600]]
输出:[[5, 3, 600], [4, 3, 500], [6,1,1000], [3,1,3000], [2, 1, 1000]]

2.4 例4

例4
输入:demands: [[1, 5000]];
stocks: [[2, 1300], [3, 1700], [4, 900], [5, 1400], [6, 1200]]
lines: [[2, 1, 1, 1000],
[3, 2, 1, 200],
[7,2,2,2000],
[4, 3, 1, 700],
[5, 4, 1, 500],
[6, 5, 1, 1000]]
输出:[[4, 3, 700], [7,2,2000], [3, 2, 1800], [2, 1, 5000]]

2.5 例5

例5可视化图
输入:demands: [[1, 1000]];
stocks: [[2, 100], [3,500], [4, 200], [5, 100], [6, 300]]
lines: [[2, 1, 1, 500],
[3, 1, 2, 500],
[4, 2, 1, 100],
[5, 2, 2, 100],
[6, 4, 1, 100]]
输出:[[6, 4, 100], [5, 2, 100], [4,2,300], [3, 1, 500], [2,1,500]]

2.6 例6

例6可视化图
输入:demands: [[1, 1000]];
stocks: [[2, 100], [3,500], [4, 200], [5, 100], [6, 300],[7, 500]]
lines: [[2, 1, 1, 500],
[3, 1, 2, 100],
[4, 2, 1, 100],
[5, 2, 2, 100],
[6, 4, 1, 100],
[7, 3, 1, 50 0]]
输出:[[7, 3, 500], [3, 1, 1000]]
先找到节点2,发现节点2的库存不够弧(2,1,1,500)的运输批量,然后找到节点3,可以运输500割单位,此时还剩500个单位的需求为满足。然后找节点2的上游,发现节点2、4、5的总库存数量为400,达不到弧(2,1,1,500)的运输批量。继续搜索到节点3的上游节点7,发现节点7的库存为500,够弧(7,3,1,100)的运输批量,且刚好够弧(3,1,2,500)的运输批量,此时需求完全被满足,结束。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值