2830. 销售利润最大化
考点
- 划分DP
- 线性DP
思路
一、问题抽象与建模
给定一排编号为 \[ 0,1,2,\dots,n-1 \] 的连续房屋,以及若干个销售方案(offer)。每个销售方案可以抽象为一个三元组: \[ (s, e, g) \] 其中:
- \(s\):方案覆盖的起始房屋编号
- \(e\):方案覆盖的结束房屋编号
- \(g\):接受该方案所获得的收益
若选择一个方案 \((s,e,g)\),则区间 \([s,e]\) 内的房屋将被整体出售,不能再与任何覆盖该区间的其他方案同时选择。
目标: 在所有互不重叠的方案中,选择若干个,使得总收益最大。
该问题本质上是一个带权不相交区间选择问题,但由于区间端点均落在连续整数轴上,可进一步转化为前缀动态规划问题。
二、动态规划状态定义
定义状态函数: \[ f(i) \] 表示: 仅考虑房屋编号位于区间 \([0,\, i-1]\) 内的所有方案时,所能获得的最大收益。
说明:
- \(f(0)=0\):不考虑任何房屋时,收益为 0
- 最终答案为 \(f(n)\)
该定义的关键在于: 状态以房屋编号的前缀为边界,而非以方案数量为边界,使得“不相交”约束自然体现在状态转移中。
三、状态转移方程
在计算 \(f(i)\) 时(\(1 \le i \le n\)),考虑两种可能:
1. 不使用任何以 \(i-1\) 结尾的方案
此时最优收益与前一状态相同: \[ f(i) = f(i-1) \]
2. 使用某个以 \(i-1\) 结尾的方案
设存在方案 \((s,\, i-1,\, g)\),若选择该方案:
- 区间 \([s,\, i-1]\) 被占用
- 之前可接上的最优状态为 \(f(s)\)
对应收益为: \[ f(s) + g \]
3. 综合转移
综合上述两种情况,状态转移方程为: \[ f(i) = \max \left( f(i-1), \max_{(s,\, i-1,\, g)} \left\{ f(s) + g \right\} \right) \]
四、实现策略与复杂度分析
分桶思想
为了高效枚举“以 \(i-1\) 结尾的所有方案”,将所有方案按结束位置分桶:
ends[e]:存储所有结束位置为e的方案 \((s,g)\)
这样在计算 \(f(i)\) 时,只需遍历
ends[i-1]。
时间复杂度
- 每个方案仅被处理一次
- 总时间复杂度:
\[ O(n + m) \]
其中 \(m\) 为方案数量。
空间复杂度
- 状态数组 \(f\):\(O(n)\)
- 分桶存储方案:\(O(m)\)
五、AC代码
1 | class Solution { |
六、小结
- 问题关键在于将“不相交区间选择”转化为前缀最优子结构
- 状态 \(f(i)\) 的定义使得区间不重叠条件天然成立
- 按右端点分桶可以在线性时间内完成状态转移
- 该建模方式适用于一类“区间落在整数轴上的加权选择问题”