← 返回编程题库
coding-min-cost-tickets-train-pass中等免费版2000ms未尝试

购买地铁通票的最小总花费

Minimum Cost for Train Travel Passes

开始编码

你需要乘地铁通勤,运营方提供三种通票1-day 通票(仅当天有效)、7-day 通票(购买当日及之后连续 6 个自然日有效)、30-day 通票(购买当日及之后连续 29 个自然日有效),价格分别记作 costs = [c1, c7, c30]。你已经预知了一年中所有要乘地铁的日期,记作 days(按天数升序的整数数组,每个元素 ∈ [1, 365])。出行日必须持有至少一张当日有效的通票,非出行日则不需要任何通票。请计算覆盖所有出行日所需的最小总花费

请实现 solution(days: list[int], costs: list[int]) -> int,返回最小整数总花费。边界:days 为空返回 0;若 days 非严格递增(无序或含重复),抛 ValueError

示例 A —— solution([1, 4, 6, 7, 8, 20], [2, 7, 15]) 返回 11。最优方案:第 1 天买一张 1-day 通票(覆盖第 1 天)、第 3 天买一张 7-day 通票(覆盖 3..9,吃下出行日 4/6/7/8)、第 20 天买一张 1-day 通票(覆盖第 20 天)。总计 2 + 7 + 2 = 11。注意「永远买能覆盖最多天的通票」这种贪心会失败:30-day 通票要 15 元,比这里的 11 元贵。

示例 B —— solution([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 30, 31], [2, 7, 15]) 返回 17。第 1 天买一张 30-day 通票(15 元)覆盖 1..30,吃下前面密集的 10 个出行日;第 31 天买 1-day 通票(2 元)覆盖落单的最后一天。总计 15 + 2 = 17。如果改成「两张 7-day 通票」覆盖前 10 天(7 + 7 = 14),还要再为第 30、31 天各加一张 1-day 通票,总计 14 + 2 + 2 = 18,反而更贵。

示例 C —— solution([], [2, 7, 15]) 返回 0。不出行就不花钱。

这道题是沿连续日历轴做一维动态规划的经典问题(LeetCode 983 的标准设定),也是「批量折扣 vs 按次付费」这一普遍成本优化场景的最小可执行模型。在做市/量化场景下也有完全同构的对应:交易台在「单笔撮合费 vs 月度行情订阅 vs 年度托管套餐」之间挑选时,面对的就是同样的权衡——支付更高的固定费用换取摊薄后的按次成本,或者直接按次付费、不买套餐。这个 DP 把权衡精确编码:每个出行日比较「再买一张 1-day 通票的边际成本」与「锁一张 7-day/30-day 通票后的摊薄成本」。最终递推式是:出行日 dp[d] = min(dp[d−1] + c1, dp[max(d−7, 0)] + c7, dp[max(d−30, 0)] + c30),非出行日 dp[d] = dp[d−1],时间空间复杂度都是 O(D),其中 D = max(days) ≤ 365,与 days 长度无关。

约束条件

  • 0 ≤ len(days) ≤ 365
  • 1 ≤ days[i] ≤ 365(年内日期序号)
  • days 严格递增——出现重复或乱序应抛 `ValueError`
  • len(costs) == 3(三种通票价格 `[c1, c7, c30]`,对应 1-day、7-day、30-day)
  • 1 ≤ costs[i] ≤ 1000
  • `days` 为空时返回 0(不出行就不用买票)
  • 返回最小总开销(整数)

样例

Case 1 · classic LC983 example one

输入: [[1,4,6,7,8,20],[2,7,15]]

期望: 11

经典 LeetCode 983 样例。最优策略:第 1 天买 1-day 通票(2),第 3 天买 7-day 通票(7,覆盖 4..10 包含 4/6/7/8),第 20 天买 1-day 通票(2),合计 2+7+2=11。

Case 2 · classic LC983 example two with 30-day pass

输入: [[1,2,3,4,5,6,7,8,9,10,30,31],[2,7,15]]

期望: 17

经典 LeetCode 983 样例二。第 1 天买 30-day 通票(15,覆盖 1..30),第 31 天买 1-day 通票(2)。合计 17。

最近提交

还没有提交记录。

编码区

实现 solution(...)。本地运行当前支持 Python 可见样例;服务端提交会运行可见样例和隐藏测试。

加载编辑器...
计时0:00

默认展示公开样例。点击「运行样例」后会在这里显示实际输出;点击「提交评测」会进入隐藏测试。

Case 1 · classic LC983 example one

输入: [[1,4,6,7,8,20],[2,7,15]]

期望: 11

经典 LeetCode 983 样例。最优策略:第 1 天买 1-day 通票(2),第 3 天买 7-day 通票(7,覆盖 4..10 包含 4/6/7/8),第 20 天买 1-day 通票(2),合计 2+7+2=11。

Case 2 · classic LC983 example two with 30-day pass

输入: [[1,2,3,4,5,6,7,8,9,10,30,31],[2,7,15]]

期望: 17

经典 LeetCode 983 样例二。第 1 天买 30-day 通票(15,覆盖 1..30),第 31 天买 1-day 通票(2)。合计 17。