hihoCoder #1157 建造金字塔
这道题我想了一天才想清楚做法。AC 了之后去看别人写的题解,都是三言两语意识流式描述,我并不能读懂。我觉得很自卑,为何人家解这道题如此轻松。不过,我还是决定把我的解法写下来,并且一定要写清楚。
思路
我想多数人见到这个题目的想法都是:先按照某种方式对三角形排序,再设法 DP 。大方向确实如此。我的做法是:「以三角形底边的右端点坐标为第一关键字从小到大,以三角形底边的左端点坐标为第二关键字从大到小」排序。记排序后的 \(n\) 个三角形为:\(T_1, T_2, \dots, T_n\) ,如此排序使得:
- 所有被 \(T_i\) 覆盖且不与 \(T_i\) 重合的三角形都排在 \(T_i\) 前面
- 设 \(0 \le k< j < i \le n\) 且 \(T_j \not\subseteq T_i, T_k \not\subseteq T_i\) 那么 \((T_k \cap T_{i}) \subseteq (T_j \cap T_i)\)
我不清楚是否还有别的排序方法也能满足上面两个条件,不过其他排序方法只要满足上述两性质,都可进而采用下面要讲的 DP 方法。
DP 状态 \(\DeclareMathOperator{\DP}{DP}\)
\(\DP_i\) 表示「只在前 \(i\) 个金字塔(即三角形)中选择一些建造并且一定建造第 \(i\) 座金字塔,所能获得的最大收益」。
边界条件
为了方便我们定义第 \(0\) 座金字塔为 \((-\infty, 0, 0)\) 。
边界条件为 \(\DP_0 = 0\) 。
转移方程
\(\left| T \right|\) 表示(等腰直角)三角形 \(T\) 的 面积。
复杂度 \(O(N^2)\) 。
这就是我的思路,当然还可以做一些小优化。代码就不贴了,我的目标是把思路说清楚,思路清楚了,代码并不难写。
总结
这道题目应当算作简单题,虽然我解得并不轻松。这个问题中,三角形其实可以简化为底边所表示的线段,设底边长为 \(l\),则三角行面积 \(s\) 可表为 \(s = s(l) =l^2/4\) 。这个问题可一般化为:给定若干条 \(x\) 轴上的线段,每条线段有一个收益值,另外给出一个成本函数 \(cost(l)\) 。其他部分和原具体问题相似,不赘述。