最少补货次数避免缺货
Min Replenishments to Avoid Stockout
开始编码你是某只中频做市策略的库存管理员。每个交易日开盘前,prime broker 会告诉你今天最多可以紧急电汇多少股进库存(refill_caps[i],不同日子额度可能不一样——broker 那边的对手方流动性也是浮动的);与此同时,你已经从研究台拿到了今天客户预计要从你这里净买走多少股(drains[i])。每一笔电汇都要走一次结算流程,都会消耗一次 ops 的人工,所以你想知道:在保证任何一日收盘时库存都不能为负(一旦负库存就会触发裸卖空告警,整个台子停摆)的前提下,最少需要发起多少笔补货电汇?
形式化:实现 solution(initial: float, drains: list[float], refill_caps: list[float]) -> int。从初始库存 initial 开始,按顺序处理每一期 i = 0, 1, ..., n−1:在第 i 期开始时你可以选择是否使用 refill_caps[i] 这一额度(一旦使用,就把全额 refill_caps[i] 加到库存上,不能只用一部分——电汇就是这样,不分段),随后该期的 drains[i] 从库存中扣除。要求每一期结束后库存都 ≥ 0;返回总共需要使用的补货次数的最小值。如果某些 drain 实在大到任何补货组合都填不平(库存必然在某期变负),返回 −1。
举例:solution(10, [5, 3, 4], [7, 2, 8]) 应返回 1——前两期分别 drain 5、3 后库存还剩 10−5−3 = 2;第三期 drain 4 会让库存掉到 −2,必须补货。可选额度有过去三期的 [7, 2, 8],挑最大的 8 补一次,库存变成 6 ≥ 0,全程一次补货搞定。再如 solution(5, [3, 6, 2], [1, 4, 10]) 应返回 2——第一期没事;第二期 drain 6 把库存打到 −4,从 [1, 4] 里挑 4 补一次(count=1),库存 0;第三期 drain 2 又打到 −2,从 [1, 10] 里挑 10 补一次(count=2),结束。
朴素的“试遍所有补货子集”的指数枚举对 5 万长度的输入毫无希望。这题的标准解法是贪心 + 最大堆:扫一遍序列,把每期的额度先压进堆里、然后扣 drain;一旦库存变负,就从堆里反复 pop 出当前最大的额度补进来,每补一次 count++,直到库存非负或堆空(堆空则 −1)。这套“事后挑最大额度追认补货”的等价改写,是贪心算法在 inventory-control 类问题里的经典套路,也是这题被放在“贪心 + 区间”簇里的理由。
约束条件
- 0 ≤ len(drains) == len(refill_caps) ≤ 50000
- 0.0 ≤ drains[i] ≤ 10⁹(每期的客户净买出量;≥ 0 表示库存只减不增——不存在“负的 drain”)
- 0.0 < refill_caps[i] ≤ 10⁹(每期 broker 提供的补货额度上限;严格大于 0,避免“调用一次 0 股的电汇”这种边界歧义)
- 0.0 ≤ initial ≤ 10⁹(初始库存)
- 返回 int:使每一期 drain 结束后库存均 ≥ 0 所需的最少补货笔数;若无论如何都做不到则返回 −1
- 数值上允许 1e-9 量级的浮点累积误差——在合理输入下答案一定是整数,无需特别处理
样例
Case 1 · single late refill suffices: pick the largest cap from history
输入: [10,[5,3,4],[7,2,8]]
期望: 1
前两期 drain 5、3 后剩 2;第三期 drain 4 让库存掉到 −2。过去三期的额度堆是 {7, 2, 8},挑最大的 8 一次补到 6 ≥ 0,全程仅 1 笔补货。
Case 2 · two refills needed across two stockout events
输入: [5,[3,6,2],[1,4,10]]
期望: 2
第二期 drain 6 把库存打到 −4,从 {1, 4} 挑 4 补一笔(count=1);第三期 drain 2 又打到 −2,从 {1, 10} 挑 10 补第二笔(count=2)。
最近提交
还没有提交记录。
编码区
实现 solution(...)。本地运行当前支持 Python 可见样例;服务端提交会运行可见样例和隐藏测试。
默认展示公开样例。点击「运行样例」后会在这里显示实际输出;点击「提交评测」会进入隐藏测试。
Case 1 · single late refill suffices: pick the largest cap from history
输入: [10,[5,3,4],[7,2,8]]
期望: 1
前两期 drain 5、3 后剩 2;第三期 drain 4 让库存掉到 −2。过去三期的额度堆是 {7, 2, 8},挑最大的 8 一次补到 6 ≥ 0,全程仅 1 笔补货。
Case 2 · two refills needed across two stockout events
输入: [5,[3,6,2],[1,4,10]]
期望: 2
第二期 drain 6 把库存打到 −4,从 {1, 4} 挑 4 补一笔(count=1);第三期 drain 2 又打到 −2,从 {1, 10} 挑 10 补第二笔(count=2)。