Algorithm 找到由点集形成的三角形是否包含原点并给出总计数的算法?

Algorithm 找到由点集形成的三角形是否包含原点并给出总计数的算法?,algorithm,Algorithm,输入:S={p1,…,pn},n二维平面上的点每个点由其x和y坐标给出 为简单起见,我们假设: 原点(0,0)不在S中。 通过(0,0)的任何线L在S中最多包含一个点。 S中没有三个点位于同一条线上。 如果我们从S中选择任意三个点,我们可以形成一个三角形。所以用这种方法形成的三角形的总数是Θ(n^3) 有些三角形包含(0,0),有些不包含 问题:计算包含(0,0)的三角形数 你可以假设我们有一个O(1)时间函数Test(pi,pj,pk)如果由{pi,pj,pk}构成的三角形包含(0,0),那

输入:
S={p1,…,pn}
n
二维平面上的点每个点由其x和y坐标给出

为简单起见,我们假设:

原点(0,0)不在S中。
通过(0,0)的任何线L在S中最多包含一个点。
S中没有三个点位于同一条线上。
如果我们从S中选择任意三个点,我们可以形成一个三角形。所以用这种方法形成的三角形的总数是Θ(n^3)

有些三角形包含(0,0),有些不包含

问题:计算包含(0,0)的三角形数

你可以假设我们有一个O(1)时间函数
Test(pi,pj,pk)
如果由
{pi,pj,pk}
构成的三角形包含(0,0),那么给定S中的三个点pi,pj,pk,返回1,否则返回0。在Θ(n^3)时间内解决问题很简单(只需枚举并测试所有三角形)

描述一个用O(n logn)运行时解决这个问题的算法


我对上述问题的分析得出以下结论

有4个坐标(+、+)、(+、-)、(-)、(-)、(-){x和y坐标>0或不>0}

  • s1=坐标x<0和y>0
  • s2=x>0,y>0
  • s3=x<0,y<0
  • s4=x>0,y<0
现在我们只需要对以下组合的集合之间的点进行测试

  • S1 S2 S3
  • S1 S4
  • S2 S3
  • S3 S3 S2
  • S1 S4 S4
  • S1 S3 S4
  • S1 S2 S4
  • S2 S3 S4
  • 我现在只需要测试上述集合组合中的点(例如,s1中的一个点、s2中的一个点和s3中的一个点),并通过调用测试函数(此处假定为恒定时间函数)查看这些点包含(0,0)

    有人能在这方面指导我吗

    下图是为了澄清为什么只有一些子集(s1、s2、s4)可以包含(0,0),而有些子集(s1、s1、s3)不能包含(0,0)


    在最坏的情况下,似乎存在包含原点的Θ(n3)三角形,因为您需要它们,答案是否定的,没有更好的算法

    对于最坏的情况,考虑奇数度的正多边形<代码> N< /代码>,以原点为中心。


    下面是计算的概要。连接两个相隔
    k
    顶点的弦是Θ(k)三角形的基础。固定一个顶点;它的贡献是来自它的所有和弦的总和,产生Θ(n2),总的贡献(所有
    n
    顶点的贡献)是Θ(n3)(每个三角形计算3次,这不影响渐近性)。

    我猜我们属于同一类(基于问题的奇怪措辞),所以现在到期日已经过去了,我觉得给出我的解决方案没问题。我设法找到了nlogn算法,正如问题所述,这更像是一个巧妙地转换问题的问题,而不是一个动态规划/DaC解决方案

    注意:这不是一个详尽的证据,我把它留给你。


    首先,一些视觉观察。取一个明显包含原点的三角形

    然后,将点转换为向量

    让自己相信,任何三个点的选择,每个向量一个,都描述了一个同样包含原点的三角形

    同样,如果在不包含原点的三角形上执行上述步骤,则沿这些向量的任何点组合也不会包含原点

    由此得出的要点是,向量的大小不重要,只影响方向。此外,问题的提示是“任何直线交叉(0,0)只包含S中的一个点”,由此我们可以推断每个向量的方向是唯一的。


    因此,如果只有角度是重要的,那么就会有一些逻辑来确定给定两点的点的范围可能形成一个包围原点的三角形。为简单起见,我们假设取了S中的所有点,并将它们转换为向量,然后对它们进行归一化,有效地使所有点位于单位圆上

    沿着这个圆取两点

    然后,从每个点通过原点到圆的另一侧绘制一条线

    因此,给定这两个点,沿红色圆弧的任何点都可以形成三角形


    因此,我们的算法应该执行以下操作:

  • 取S中的每个点。制作一个二次阵列a,对于每个点,将沿单位圆(atan2(x,y))的角度添加到a(0)上≤ 艾岛≤ 2π). 让我们假设这是O(n)

  • 按递增排序O(n logn),假设我们使用合并排序

  • 计算每对(Ai、Aj)可能的三角形数。这意味着我们计算Ai+π的数量≤ Ak≤ Aj+π。由于数组已排序,我们可以使用二进制搜索来查找Ai+π和Aj+π的索引,即O(2 logn)=O(logn)

  • 然而,我们遇到了一个问题,有n^2个点,如果我们必须对每个点进行O(logn)搜索,我们就有O(n^2 logn)。所以,我们需要再做一次观察

    给定一些AiAj,我们知道Tij≤ Tik,因为Ai+π和Ak+π之间的点数必须至少等于Ai+π和Aj+π之间的点数。事实上,它正是Ai+π和Aj+π之间的计数,加上Aj+π和Ak+π之间的计数。因为我们已经知道Ai+π和Aj+π之间的计数,所以我们不知道
    int triangleCount(point P[],int n)
        int A[n], C[n], totalCount = 0;  
    
        for(i=0...n)
            A[i] = atan2(P[i].x,P[i].y);
    
        mergeSort(A);
    
        int midPoint = binarySearch(A,π);
    
        for(i=0...midPoint-1)
            int left = A[i] + π, right = A[i+1] + π;
            C[i] = binarySearch(a,right) - binarySearch(a,left);
            for(j=0...i)
                totalCount += C[j]
    
    return totalCount;