在 2D 平面中划分一组点

Posted

技术标签:

【中文标题】在 2D 平面中划分一组点【英文标题】:Partitioning a set of points in 2D plane 【发布时间】:2018-10-20 17:07:50 【问题描述】:

问题陈述是—— “给你一组 N 个点,其中 N 是偶数,N

class Point
public:
   int x, y;
   Point()x = y = 0;
   void make_point(int X, int Y) x = X; y = Y; 
   int Point:: orientation (Point &p0, Point &p1)
     Point p2 = *this;
     Point a = p1 - p0;
     Point b = p2 - p0;
     int area = (a.x * b.y) - (b.x * a.y);
     if (area > 0)return 1;
     if (area < 0)return -1;
     return 0;
   
;
int main() 
  Point p[4];
  p[0].make_point(0, 0);
  p[1].make_point(0, 1);
  p[2].make_point(1, 1);
  p[3].make_point(1, 0);
  int sz = sizeof(p) / sizeof(p[0]);
  int ans = 0;
  for (int i = 0; i < sz; i++)
    for (int j = i+1; j < sz; j++)
        int leftCnt = 0, rightCnt = 0;
        for (int k = 0; k < sz; k++)
            if (k == i || k == j)continue;
            if (p[k].orientation(p[i], p[j]) == 1)leftCnt++;
            if (p[k].orientation(p[i], p[j]) == -1)rightCnt++;
        
        if (leftCnt == rightCnt && leftCnt == (sz/2-1))ans++;
    
  
  cout << ans << '\n';

  return 0;

有没有办法优化解决方案?

【问题讨论】:

如果你能展示你自己尝试解决问题的努力是首选 - 至少向我们展示你尝试了 O(n^3) 的蛮力解决方案 - 然后你可以问如何它可以改进... 感谢您的回复。我已经添加了我的蛮力方法。 【参考方案1】:

有一个简单的方法可以在 O(n^2 log n) 时间内完成。

for each point O in the set
   for each point A /= O
      calculate the slope of the ray OA 
   sort the points by the slope (this is the n log n limiting step) 
   for each point A /= O
      determine how many points are at either side of the line OA (this is an O(1) job)

也许排序时间可以减少,因为在将极坐标转换到另一个原点时,斜率的排序数组将变得几乎排序(只需要 O(n) 时间来完全排序),但我无法证明这一点目前。

【讨论】:

请注意,对斜率进行排序不会这样做。永远移动 - 你只想得到可以在 O(n) 中完成的斜率数组中的第 k 个元素。考虑以下 - 5 个点作为五边形,6 个点在中间 - 这种情况下斜率排序将失败,因为五边形的每个点都用中点回答约束 @DavidWinder 我不明白你的例子。是的,五边形的每个点都会回答约束。该算法将按应有的方式找到它们。你的选择是什么? 所以也许我误解了你的算法:determine how many points are at either side of the line OA (this is an O(1) job) 到底是什么意思?给定 O(1) 中的排序斜率数组,你怎么能做到这一点? 我明白我没有解释清楚。将算法的内部循环可视化为旋转圆直径。它将圆圈分成两半,比如红色和蓝色。圆圈上有一些点。最初你知道有多少点是两种颜色的。然后随着直径的旋转,您知道它接下来会用它的任一端击中哪个点,因为这些点已排序。重新涂上相反的颜色。每次出现相同数量的红点和蓝点时,您就找到了答案的一个元素。当直径旋转 180° 时循环结束。 O(N) 遍历所有 N 个点,每个点 O(1)。 谢谢!我已经实现了这个算法。它对我有用并且足够高效。

以上是关于在 2D 平面中划分一组点的主要内容,如果未能解决你的问题,请参考以下文章

找到并绘制回归平面到一组点

找到一个具有最大点数的圆 ((x,y,r));给定二维平面中的一组点(x,y)

Lloyd’s 算法 和 K-Means算法

平滑2D曲线

包含一组点的多边形

二维平面三角划分