限次交易加固定手续费的最优收益
Best Trades With K Transactions and Fee
开始编码某做市策略组拿到对一只股票未来 N 个交易日的价格预测序列 prices(按时间升序)。合规与撮合费用上有两条硬约束:(1)账户每天最多完成 K 次完整往返交易(一次「买入 → 卖出」算一次),多出的指令会被风控直接拒;(2)每完成一次往返要付一笔固定撮合费 fee(与成交量无关,只看次数)。请算出在这两条约束下的事后最大累计净收益——即给定上帝视角的价格曲线,挑哪几段做、放弃哪几段,能榨出多少钱。
请实现 solution(prices: list[float], k: int, fee: float) -> float。规则细节:(a)任何时刻最多持仓一股,必须先全部卖掉才能再买;(b)fee 在每次卖出时一次性扣除,所以一次往返净收益是 卖出价 − 买入价 − fee;(c)允许做 0 次到 K 次任意整数次交易(不强制吃满 K 次),允许整段不交易;(d)期末必须空仓(不允许带仓离场);(e)若 len(prices) < 2、k == 0、或所有可行方案都不赚钱,应返回 0.0。
示例:solution([1.0, 3.0, 2.0, 8.0, 4.0, 9.0], 2, 2.0) 应返回 8.0。最优执行:第 0 天买入 (-1.0),第 3 天卖出 (+8.0),扣手续费 2.0,净赚 5.0;接着第 4 天买入 (-4.0),第 5 天卖出 (+9.0),再扣 2.0,净赚 3.0。合计 8.0。注意「第 0 天 → 第 1 天」单看也能赚 3-1-2 = 0,但把这次珍贵的交易额度 (K 只有 2) 让出来给后面更大的波段更划算——这就是 K 与 fee 联合作用让贪心失效的地方。再看 solution([1.0, 2.0, 3.0, 0.0, 2.0], 100, 0.0):K 远大于可能的交易次数,问题退化为「无限次带手续费」(这里 fee=0),最优是吃下每一段上涨:(2-1)+(3-2)+(2-0) = 4.0。
朴素地枚举「在哪几天买、在哪几天卖」是组合爆炸,不可行。关键观察是每一天结束时的状态由两个维度刻画:「现在是否持仓」与「已经用掉多少次交易额度」。前者只有 2 种取值,后者只有 K+1 种取值,所以全局只有 2(K+1) 个状态,DP 表是 O(n·K)。当 K 大到可以容纳 n // 2 次交易时,约束失效,可退化为 O(n) 一维形式。这道题是「无限次交易」与「最多两次交易」两个经典问题的合并推广,也是真实做市约束下回测「机会成本」的标准刻画——撮合预算和单笔成本会迫使你放弃小波段、保留交易额度去吃更大的趋势。
约束条件
- 0 ≤ len(prices) ≤ 100000
- 0 ≤ k ≤ 100000(k=0 时不允许任何交易)
- 0 < prices[i] ≤ 10⁶(正实数报价,单位:元/股)
- 0 ≤ fee ≤ 10⁶(每完成一次完整往返交易固定收取一次)
- 同一时刻最多持有一股;必须先卖才能再买
- 期末必须空仓(不允许带着仓位走出窗口)
- 若所有可行计划都亏损,返回 `0.0`(即「不交易」)
- 返回值允许 1e-6 的浮点误差
样例
Case 1 · two round trips, no fee
输入: [[3,2,6,5,0,3],2,0]
期望: 7
K=2、fee=0。最优执行:第 1 天买 (-2.0)、第 2 天卖 (+6.0)、第 4 天买 (-0.0)、第 5 天卖 (+3.0),累计 (6-2)+(3-0)=7.0。三次交易总收益更高,但 K=2 的预算把第三次堵死了。
Case 2 · two round trips with per-trade fee
输入: [[1,3,2,8,4,9],2,2]
期望: 8
K=2、fee=2。最优是「第 0 天买 (1.0) → 第 3 天卖 (8.0)」净赚 8-1-2=5;再「第 4 天买 (4.0) → 第 5 天卖 (9.0)」净赚 9-4-2=3。合计 8.0。注意「第 0 天 → 第 1 天」单笔只赚 3-1-2=0,把这次交易让位给后面的大波段更划算。
最近提交
还没有提交记录。
编码区
实现 solution(...)。本地运行当前支持 Python 可见样例;服务端提交会运行可见样例和隐藏测试。
默认展示公开样例。点击「运行样例」后会在这里显示实际输出;点击「提交评测」会进入隐藏测试。
Case 1 · two round trips, no fee
输入: [[3,2,6,5,0,3],2,0]
期望: 7
K=2、fee=0。最优执行:第 1 天买 (-2.0)、第 2 天卖 (+6.0)、第 4 天买 (-0.0)、第 5 天卖 (+3.0),累计 (6-2)+(3-0)=7.0。三次交易总收益更高,但 K=2 的预算把第三次堵死了。
Case 2 · two round trips with per-trade fee
输入: [[1,3,2,8,4,9],2,2]
期望: 8
K=2、fee=2。最优是「第 0 天买 (1.0) → 第 3 天卖 (8.0)」净赚 8-1-2=5;再「第 4 天买 (4.0) → 第 5 天卖 (9.0)」净赚 9-4-2=3。合计 8.0。注意「第 0 天 → 第 1 天」单笔只赚 3-1-2=0,把这次交易让位给后面的大波段更划算。