计算二维中包含原点的多边形数量

问题描述 投票:0回答:1

假设我们在 2D 空间中有 n 个处于凸位置的点。精确地选择(n,k)个不同的凸k边形(非退化)。是否有任何现有算法可以在 O(n log n) 时间内运行(对于固定 k)来计算包含原点的多边形数量?

我试图在文献中寻找任何此类算法,但只找到了 k=3 的算法。

algorithm geometry polygon computational-geometry counting
1个回答
0
投票

这是一个扫线算法。

首先,计算多边形数。然后扫一圈线,当多边形完全处于视图中时删除不包含原点的多边形,然后删除其第一个点。

import math

def choose (n, m):
    # Special case this to avoid division by zero.
    if n < m:
        return 0
    else:
        answer = 1
        for i in range(m):
            answer = (answer * (n-i)) // (i+1)
        return answer



# I assume that points are (x, y) pairs here.
def count_poly_containing_origin (k, points):
    # Start with total number of polygons, subtract those without origin.
    polys = choose(len(points), k)

    # Convert ones not at origin to angle with -pi < angle <= pi
    angles = []
    for x, y in points:
        if x == 0 and y == 0:
            pass # I'm assuming closed polygons. Have this, have origin.
        else:
            angles.append(math.atan2(x, y))

    angles = sorted(angles)

    # We are going to sweep a line around. We will add each point when we
    # see it, and remove it math.pi later. When we remove the point, we
    # subtract off how many polygons it is in that do not contain the origin.
    #
    #
    # i represents what we will remove next. j represents what we will add
    # next, selected is how many points are currently selected.
    #
    # We start nothing selected, added, or removed.

    i = j = selected = 0
    while i < len(angles):
        if i <= j:
            if angles[j] < angles[i] + math.pi:
                # add point
                selected += 1
                j += 1
                # Do we need to wraparound?
                if j == len(angles):
                    j = 0
            else:
                # remove point
                selected -= 1
                i += 1
                # Remove the polygons containing angles[i] and not the origin.
                polys -= choose(selected, k-1)
        else:
            if angles[j] < angles[i] - math.pi:
                # add point
                selected += 1
                j += 1
            else:
                # remove point
                selected -= 1
                i += 1
                # Remove the polygons containing removed point and not the origin.
                polys -= choose(selected, k-1)
 
    return polys

对于固定

k
,这是一个
O(n log(n))
算法。对于较大的
k
,瓶颈在于重复计算
choose(m, k-1)
进行减法。可以通过在
O(n)
中为其创建查找表来加快速度。 (留给读者作为练习。)

© www.soinside.com 2019 - 2024. All rights reserved.