📌  相关文章
📜  N个轴平行矩形之间缺少顶点(1)

📅  最后修改于: 2023-12-03 15:18:04.567000             🧑  作者: Mango

题目:

给定平面直角坐标系上 $N$ 个轴平行矩形,其中第 $i$ 个矩形左上角坐标为 $(x_{i1},y_{i1})$,右下角坐标为 $(x_{i2},y_{i2})$,保证 $x_{i1}<x_{i2}$,$y_{i1}<y_{i2}$,且所有矩形两两不重叠。请编写一个程序,计算这些矩形之间缺少顶点的个数。

思路:

我们可以将给定的 $N$ 个矩形的所有顶点按照从左到右、从上到下的顺序排序,并用扫描线来统计缺少顶点的个数。

我们先将所有的顶点按照排序规则排序。排序规则是:$x$ 坐标越小的点排在越前面,如果 $x$ 坐标相同,则 $y$ 坐标越小的点排在越前面。

例如,下面的矩形:

   (2,6) ________ (7,6)
        |        |
        |        |
        |        |
   (2,2) -------- (7,2)

对应的顶点为:

(2,2) (2,6) (7,2) (7,6)

排序结果为:

(2,2) (2,6) (7,2) (7,6)

接下来,我们用一条扫描线从上到下依次扫描所有的顶点。

扫描到一个顶点时,将其加入一个激活边集 $E$(即正在受到扫描线影响的矩形的边)。同时,如果该点是矩形的右上角或者左下角,则该矩形的另一个顶点从激活边集 $E$ 中移除。

每次扫描到一个新的点时,我们需要统计激活边集 $E$ 中所有相邻的线段之间的缺少的顶点个数。

对于相邻的两条线段,如果它们共同包含一个矩形的边,则它们之间没有缺少的顶点。否则,它们之间必然有一个缺少的顶点。

具体的实现方法是,对于激活边集 $E$ 中任意相邻的两条线段 $e_1$ 和 $e_2$,我们判断这两条线段是否分别来自两个不同的矩形。如果是,则它们之间必然有一个缺少的顶点。

需要注意的是,在扫描过程中,我们不能重复计算同一条线段之间的缺少的顶点个数。为了避免重复,我们可以使用一个标记数组 $vis$ 来记录已经计算过的线段。

代码实现:

# -*- coding: UTF-8 -*-
def count_missing_vertices(n, rectangles):
    # 将所有顶点排序
    points = []
    for i in range(n):
        x1, y1, x2, y2 = rectangles[i]
        points.append((x1, y1))
        points.append((x2, y2))
        points.append((x1, y2))
        points.append((x2, y1))
    points.sort()

    # 扫描线统计缺少顶点的个数
    ans = 0
    E = set()
    vis = set()
    for i in range(len(points)):
        x, y = points[i]
        for e in E:
            if e[0] != x:
                u, v = e
                if (u, v, x, v) in vis:
                    continue
                vis.add((u, v, x, v))
                vis.add((x, v, u, v))
                ans += 1
        E = {e for e in E if e[1] != y}
        for j in range(i + 1, len(points)):
            if points[j][1] != y:
                break
            if y == rectangles[points[j][2] // 4][1] and x != rectangles[points[j][2] // 4][0]:
                edges = [(points[j][0], y), (x, points[j][1])]
                edges.sort()
                E.add((edges[0], edges[1]))
    return ans

复杂度分析

时间复杂度:$O(N^2 \log N)$

空间复杂度:$O(N)$