在 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 平面中划分一组点的主要内容,如果未能解决你的问题,请参考以下文章