切割绳子价值最小化
问题重述
-
有若干根绳子(或一根总绳)
-
最多切 K 刀,得到若干段
-
段越短,价值越低,且呈指数下降
-
目标:总价值最小
-
每次切割的收益 = 切割前段价值 - 切割后两段价值之和(收益 > 0 才值得切)
数学模型
根据题目可见,尽量把最长段变小就是合理解。但是这里有一个细节,一个绳直接切一刀把两段压入数组,再次切这个绳会出现12 6 6 6 3 3 这种情况,实际上两刀切到一个绳子上完全可以变成4 4 4的段,这也是为什么要用价值优先队列转移
设一段长度为 x,其价值为:
val(x) = e^(-λx) 或 val(x) = 1 / x^p
切割收益:
gain = val(x) - val(a) - val(x-a)
每次选 gain 最大的段切一刀
代码略
常见价值函数替换表
| 物理意义 | 公式 | 代码 |
|---|---|---|
| 指数衰减 | e^(-λx) | exp(-LAMBDA * x) |
| 平方反比 | 1/x² | 1.0 / (x * x) |
| 幂律 | 1/x^p | pow(x, -P) |
| 对数 | -ln(x) | -log(x) |
| 线性 | ax + b | A * x + B |
为什么贪心是对的?(简要证明)
交换论证:
-
假设最优解不是每次切收益最大的段
-
存在一次切割 A(收益大)未被选,另一次切割 B(收益小)被选
-
交换这两次切割顺序,总价值不会变差
-
因此贪心选择是最优的
复杂度分析
-
时间:O(K log K)
-
空间:O(K)