# 一个 Treemap 的近似绘制算法

# 符号定义

对一个矩形 rr, 令 h(r)h(r) 为其高,w(r)w(r) 为其宽。于是其面积为 a(r):=h(r)w(r)a(r):=h(r)w(r),其周长为 p(r):=h(r)+w(r)p(r) := h(r) + w(r),纵横比为 ρ(r):=max⁡{h(r),w(r)}min⁡{h(r),w(r)}\rho(r):=\frac{\max\{h(r),w(r)\}}{\min\{h(r),w(r)\}}. 若集合 R={ri∣i=1,2,…,n}\mathscr R=\{r_i|i=1,2,\dots,n\},定义其周长和 ps(R):=∑r∈Rp(r)ps(\mathscr{R}) := \sum_{r \in \mathscr{R}}p(r), 其最大周长 pm(R):=max⁡r∈Rp(r)pm(\mathscr{R}):=\max_{r \in \mathscr{R}}p(r), 其最大长宽比为 ρ(R):=max⁡r∈Rρ(r)\rho(\mathscr{R}) := \max_{r\in\mathscr{R}} \rho(r). (由于周长和半周长之间只相差一个常系数,因此是无关紧要的。为方便,我们姑且称其为周长。)

# 问题

对于矩形的分划,先前已有三个基本的问题作为铺垫:

  • 如何将原矩形 R0R_0 划分成矩形集 R\mathscr{R}, 使得周长和 ps(R)ps(\mathscr{R}) 最小。称为周长和最小问题 (PERI-SUM)。
  • 如何将原矩形 R0R_0 划分成矩形集 R\mathscr{R}, 使得最大周长 pm(R)pm(\mathscr{R}) 最小。称为最大周长最小问题 (PERI-MAX)。
  • 如何将原矩形 R0R_0 划分成矩形集 R\mathscr{R}, 使得最大长宽比 ρ(R)\rho(\mathscr{R}) 最小。称为最大长宽比最小问题 (ASPECT-RATIO)。

以上三个问题都是 NP-hard 问题 。

而本篇论文中的算法,可以在O(nlog⁡n)O(n\log n) 复杂度内使矩形的划分R\mathscr{R} 同时达到:

  • PERI-SUM 问题的23\frac{2}{\sqrt{3}} 倍最优解
  • PERI-MAX 问题的1.251.25 倍最优解
  • ASPECT-RATIO 问题中,控制ρ(R)≤max⁡{ρ(R0),3,1+max⁡i=1,…,n−1ai+1ai}\rho(\mathscr{R}) \leq \max\{\rho(R_0),3,1+\max_{i=1,\dots,n-1}\frac{a_{i+1}}{a_i}\}

# 算法过程及分析

首先,我们引入一个引理,以说明算法的每一步操作的结果及其性质。

引理 1 令A={b1,b2,…,bm}A=\{b_1,b_2,\dots,b_m\},其中bi≤bi+1,i=1,2,…,m−1b_i \leq b_{i+1},\,i=1,2,\dots,m-1。令α=∑i=1mbi\alpha = \sum_{i=1}^mb_i,则∃k∈Z\exists k \in \mathbb{Z} 使得∑i=1k−1bi<α3≤∑i=1kbi\sum_{i=1}^{k-1}b_i < \frac{\alpha}{3} \leq \sum_{i=1}^kb_i。于是以下两结论之一必成立:

  1. α3≤bm\frac{\alpha}{3} \leq b_m
  2. bm<α3b_m<\frac{\alpha}{3},k≤m−2k\leq m-2 且∑i=1kbi<5α9\sum_{i=1}^kb_i<\frac{5\alpha}{9}(且当bm−1≤α6b_{m-1} \leq \frac{\alpha}{6} 时,∑i=1kbi<α2\sum_{i=1}^kb_i < \frac{\alpha}{2})

根据简单的大小估计和放缩就可以证明了。

# 算法

输入:一个矩形RR,一个正实数集合A:={ai,ai+1,…,ai+∣A∣−1}A:= \{a_i,a_{i+1},\dots,a_{i+|A|-1}\},满足∣A∣≥2|A| \geq 2,ai≤ai+1≤⋯≤ai+∣A∣−1a_i\leq a_{i+1} \leq \cdots \leq a_{i+|A|-1} 且∑a∈A=a(R)\sum_{a \in A} = a(R)。在不失一般性的前提下,假设h(R)≤w(R)h(R) \leq w(R)。

输出:一个关于RR 的划分{ri,ri+1,…,ri+∣A∣−1}\{r_i,r_{i+1},\dots,r_{i+|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))
        # repeated the recursive process until the A has only one element 
    else:
        return R # while len(A) = 1, return the rectangle

# 算法的复杂度

引理 2 给定一个矩形R0R_0 和一个包含nn 个正实数的集合A0A_0,使得∑a∈A0a=a(R0)\sum_{a \in A_0} a = a(R_0),则函数 dissect(R0,A0) 返回一个关于A0A_0 的划分需要的时间复杂度为O(nlog⁡n)O(n\log n)。

根据算法的内容来看,复杂度是显然的。

定理 1 给定一个矩形R0R_0 和一个包含nn 个正实数的集合A0={a1,a2,…,an}A_0=\{a_1,a_2,\dots,a_n\},使得∑a∈Aa=a(R0)\sum_{a \in A}a = a(R_0),令R={r1,r2,…,rn}\mathscr{R}=\{r_1,r_2,\dots,r_n\} 为 dissect(R0,A0) 的输出结果,其中a(ri)=ai,ai∈A0a(r_i) = a_i,a_i \in A_0。令R′\mathscr{R}' 为递归过程中得到的全体矩形组成的集合,则有:

  1. 对任一r∈R∪R′r \in \mathscr{R} \cup \mathscr{R}',有

ρ(r)≤max⁡{ρ(R0),3,1+max⁡i=1,2,…,n−1ai=1ai}.\rho(r) \leq \max\left\{\rho(R_0),3,1+\max_{i=1,2,\dots,n-1}\frac{a_{i=1}}{a_i}\right\}.

  1. 设划分得到的最大周长 (PERI-MAX) 最小值为OPTpmOPT_{pm},则

ps(R)OPTpm≤23(≈1.1547).\frac{ps(\mathscr{R})}{OPT_{pm}} \leq \frac{2}{\sqrt{3}}(\approx 1.1547).

  1. 设划分得到的周长和最小值为OPTpsOPT_{ps},则

ps(R)OPTps≤54.\frac{ps(\mathscr{R})}{OPT_{ps}} \leq \frac{5}{4}.

# 对纵横比 (ASPECT-RATIO) 的分析

引理 1 令R1R_1 和R2R_2 是一个复合矩形R∈RR\in\mathscr R 的左右孩子,设al≤al+1≤⋯≤ama_l\leq a_{l+1} \leq \cdots \leq a_m 是A(R)A(R) 中的实数。