# 一个 Treemap 的近似绘制算法
# 符号定义
对一个矩形 r, 令 h(r) 为其高,w(r) 为其宽。于是其面积为 a(r):=h(r)w(r),其周长为 p(r):=h(r)+w(r),纵横比为 ρ(r):=min{h(r),w(r)}max{h(r),w(r)}. 若集合 R={ri∣i=1,2,…,n},定义其周长和 ps(R):=∑r∈Rp(r), 其最大周长 pm(R):=maxr∈Rp(r), 其最大长宽比为 ρ(R):=maxr∈Rρ(r). (由于周长和半周长之间只相差一个常系数,因此是无关紧要的。为方便,我们姑且称其为周长。)
# 问题
对于矩形的分划,先前已有三个基本的问题作为铺垫:
- 如何将原矩形 R0 划分成矩形集 R, 使得周长和 ps(R) 最小。称为周长和最小问题 (PERI-SUM)。
- 如何将原矩形 R0 划分成矩形集 R, 使得最大周长 pm(R) 最小。称为最大周长最小问题 (PERI-MAX)。
- 如何将原矩形 R0 划分成矩形集 R, 使得最大长宽比 ρ(R) 最小。称为最大长宽比最小问题 (ASPECT-RATIO)。
以上三个问题都是 NP-hard 问题 。
而本篇论文中的算法,可以在O(nlogn) 复杂度内使矩形的划分R 同时达到:
- PERI-SUM 问题的32 倍最优解
- PERI-MAX 问题的1.25 倍最优解
- ASPECT-RATIO 问题中,控制ρ(R)≤max{ρ(R0),3,1+maxi=1,…,n−1aiai+1}
# 算法过程及分析
首先,我们引入一个引理,以说明算法的每一步操作的结果及其性质。
引理 1 令A={b1,b2,…,bm},其中bi≤bi+1,i=1,2,…,m−1。令α=∑i=1mbi,则∃k∈Z 使得∑i=1k−1bi<3α≤∑i=1kbi。于是以下两结论之一必成立:
- 3α≤bm
- bm<3α,k≤m−2 且∑i=1kbi<95α(且当bm−1≤6α 时,∑i=1kbi<2α)
根据简单的大小估计和放缩就可以证明了。
# 算法
输入:一个矩形R,一个正实数集合A:={ai,ai+1,…,ai+∣A∣−1},满足∣A∣≥2,ai≤ai+1≤⋯≤ai+∣A∣−1 且∑a∈A=a(R)。在不失一般性的前提下,假设h(R)≤w(R)。
输出:一个关于R 的划分{ri,ri+1,…,ri+∣A∣−1}。
我把代码写成了类似 Python 的伪代码形式
| def dissect(R,A): |
| if len(A) > 1: |
| if sum(A)/3 <= max(A): |
| A1 = [a[i],a[i+1],...,a[i+len(A)-2]] |
| A2 = [a[i+len(A)-1]] |
| else: |
| k = 0 |
| A1 = [] |
| while sum(A1) < sum(A)/3: |
| A1.append(a[i+k]) |
| |
| h(R1) = h(R2) = h(R) |
| |
| w(R1) = w(R)*sum(A1)/sum(A) |
| w(R2) = w(R)*sum(A2)/sum(A) |
| |
| return dissect(R1,A1).extend(dissect(R2,A2)) |
| |
| else: |
| return R |
# 算法的复杂度
引理 2 给定一个矩形R0 和一个包含n 个正实数的集合A0,使得∑a∈A0a=a(R0),则函数 dissect(R0,A0)
返回一个关于A0 的划分需要的时间复杂度为O(nlogn)。
根据算法的内容来看,复杂度是显然的。
定理 1 给定一个矩形R0 和一个包含n 个正实数的集合A0={a1,a2,…,an},使得∑a∈Aa=a(R0),令R={r1,r2,…,rn} 为 dissect(R0,A0)
的输出结果,其中a(ri)=ai,ai∈A0。令R′ 为递归过程中得到的全体矩形组成的集合,则有:
- 对任一r∈R∪R′,有
ρ(r)≤max{ρ(R0),3,1+i=1,2,…,n−1maxaiai=1}.
- 设划分得到的最大周长 (PERI-MAX) 最小值为OPTpm,则
OPTpmps(R)≤32(≈1.1547).
- 设划分得到的周长和最小值为OPTps,则
OPTpsps(R)≤45.
# 对纵横比 (ASPECT-RATIO) 的分析
引理 1 令R1 和R2 是一个复合矩形R∈R 的左右孩子,设al≤al+1≤⋯≤am 是A(R) 中的实数。