【问题标题】:Find number of rectangles from a given set of coordinates从给定的一组坐标中查找矩形的数量
【发布时间】:2013-10-05 22:07:56
【问题描述】:

我必须从给定的一组坐标中找到最大数量的矩形。

考虑以下坐标在 X Y 坐标系中给出 3 10, 3 8, 3 6, 3 4, 3 0, 6 0, 6 4, 6 8, 6 10,

如何判断以下坐标是否形成矩形 (3,0) (3,4) (6,4) (6,0)

运行时间限制:0.1 秒

谢谢

【问题讨论】:

  • 确定问题是什么。 4个点组成一个矩形或给定点可以形成多少个矩形?
  • 实际上,我如何验证 4 个点形成一个矩形以及如何找到可能的矩形的最大数量
  • 这是一个 ACM 问题吗?
  • 不是 ACM 的,来自一本带有练习题的书
  • 给定点的最大数量是多少?

标签: geometry coordinates rectangles


【解决方案1】:

在“y”坐标列表中分离您的点,按“x”坐标分组。在您的情况下,您将有两个排序列表:

3: [0,4,6,8,10]
6: [0,4,8,10]

做两个列表的交集你得到:[0,4,8,10]

其中任何两个都会形成一个矩形:

[0,4] => (3,0), (3,4), (6,0), (6,4)
[0,8] => (3,0), (3,8), (6,0), (6,8)
[4,8] => (3,4), (3,8), (6,4), (6,8)
...

此解决方案仅适用于正交矩形,即边平行于 x,y 轴。

【讨论】:

  • 太棒了,我一直在努力寻找实现这一目标的方法
  • 我刚刚看到你关于正交的注释。对不起
  • 应该有一种在正交情况下旋转的方法。只是改变坐标计算。
【解决方案2】:

对于每一对点,比如 (x1, y1) 和 (x2, y2) 认为它是某个矩形的对角线。如果在初始集合中存在点 (x1, y2) 和 (x2, y1),那么我们已经找到了我们的矩形。需要注意的是,会有 2 条对角线代表同一个矩形,所以我们将最终答案除以 2。

这仅适用于平行于 x 轴或 y 轴的矩形。

伪代码 C++:

answer = 0;
set<pair<int, int>> points;

for(auto i=points.begin(); i!=std::prev(points.end()); i++)
{
    for(auto j=i+1; j!=points.end(); j++)
    {
        pair<int, int> p1 = *i;
        pair<int, int> p2 = *j;

        if(p1.first == p2.first || p1.second == p2.second)
            continue;

        pair<int, int> p3 = make_pair(p1.first, p2.second);
        pair<int, int> p4 = make_pair(p2.first, p1.second);

        if(points.find(p3) != points.end() && points.find(p4) != points.end())
            ++answer;
    }
}

return answer/2;

【讨论】:

  • 在这里帮帮我。 (1,1) (2,2) (3,1) (2,0) 是矩形吗?
  • @hasan - 它是一个矩形,但它的边不平行于坐标轴
【解决方案3】:

检查4个点是否形成一个矩形:

  1. 为每两个点计算距离。将所有内容存储在浮点数组中。
  2. 对数组进行排序。

你将有 a[0] = a[1], a[2] = a[3], a[4] = a[5]

【讨论】:

  • 您的条件是neccessary but not sufficientparallelorgram 也将满足它。由于舍入误差,比较浮点数是否完全相等是个坏主意。
  • 我对这个解决方案有点疑惑。那么这组点呢 (a,b,c,d) = (1,2),(2,1),(3,1),(4,2) a 和 b 的距离是一样的c 和 d 之间的距离,但它们不形成矩形。
  • 你必须有六个值。 a-b = c-d,a-d = b-c,a-c = b-d。最后一个是对角线。
  • 但是,如果你有一个更长的点列表,比如 100 个,你怎么能在 10k 对距离之间找到矩形所需的 3 对距离?
  • 我用很多问题评论了上述问题。我需要大量信息来为每种情况提供适当的解决方案。回答他们,我会告诉你。
【解决方案4】:

如何判断以下坐标是否形成矩形

检查差分向量是否正交,即点积为零。

检查这些坐标是否包含在您的列表中。它还检查矩形是否与坐标轴对齐,这将是一个简单得多的问题。

如果您想查找输入中的所有矩形,可以对所有四元组进行上述检查。如果由于性能原因这是不可接受的,那么您应该更新您的问题,指出您面临的问题规模和性能限制。

【讨论】:

  • 如果我理解正确,您的建议是遍历所有四倍点 (O(n^4)) 并检查是否 v 。 w = 0 对于每个四元组,其中 v = p1-p2 和 w = p3-p4 ,对吗? “这不检查这些坐标是否包含在您的列表中”到底是什么意思?您正在对给定点进行迭代,那么为什么需要该检查?
【解决方案5】:

我谦虚的提交

我假设优化次数是可能的。

【讨论】:

    【解决方案6】:

    我的方法是

    • 遍历每个点
    • 检查哪些点在该点上方,然后存储这些点的 Y 坐标,形成一条线
    • 下次当我再次找到相同的 Y 坐标时,这意味着我们找到了 1 个矩形
    • 继续遍历所有其他点做同样的事情。

    我的解决方案在 O(n^2) 中运行,但这只会是平行于 X 或 Y 轴的矩形。

    这是我上述方法的代码:

    def getRectangleCount(coordinate):
        n = len(coordinate)
        y_count = dict()
        ans = 0
        for i in range(n):
            x, y = coordinate[i]
            for j in range(n):
                dx = coordinate[j][0]
                dy = coordinate[j][1]
                if y < dy and x == dx:
                    ans += y_count.get((y, dy), 0)
                    y_count[(y, dy)] = y_count.get((y, dy), 0) + 1
        return ans
    
    
    coordinate = [[3, 10], [3, 8], [3, 6], [3, 4], [3, 0], [6, 0], [6, 4], [6, 8], [6, 10]]
    print(getRectangleCount(coordinate))
    

    【讨论】:

      【解决方案7】:

      这是一个解决方案,可以在 O(n^4) 时间内在给定的坐标点列表中找到所有唯一的矩形(不仅是那些平行于 x 或 y 轴的矩形)。

      伪代码:

      // checks if two floating point numbers are equal within a given 
      // error to avoid rounding issues
      bool is_equal(double a, double b, double e) {
          return abs(a - b) < e;
      }
      
      // computes the dot product of the vectors ab and ac
      double dot_product(Point a, Point b, Point c) {
          return (b.x - a.x) * (c.x - a.x) + (b.y - a.y) * (c.y - a.y);
      }
      
      // find all rectangles in a given set of coordinate points
      List<Rectangle> find_rectangles(List<Point> points) {
          List<Rectangle> rectangles;
      
          // sort points in ascending order by first comparing x than y value
          sort(points);
      
          for (int a = 0; a < points.size(); ++a)
              for (int b = a + 1; a < points.size(); ++b)
                  for (int c = b + 1; c < points.size(); ++c)
                      for (int d = c + 1; d < points.size(); ++d)
                          // check all angles
                          if (is_equal(dot_product(points[a], points[b], points[c]), 0.0, 1e-7) &&
                              is_equal(dot_product(points[b], points[a], points[d]), 0.0, 1e-7) &&
                              is_equal(dot_product(points[d], points[b], points[c]), 0.0, 1e-7) &&
                              is_equal(dot_product(points[c], points[a], points[d]), 0.0, 1e-7))
                              // found rectangle
                              rectangles.add(new Rectangle(points[a], points[c], points[d], points[b]));
      
          return rectangles;
      }
      

      说明:

      对于一组给定的点 A, B, C, Ddefine a rectangle,我们可以检查是否所有角度都是 90°,这意味着所有不平行的边都是正交的。

      由于我们可以仅通过 dot product 为 0 来检查此属性,因此这是最有效的方法(无需进行平方根计算来计算边长)。

      先对点进行排序可以避免由于排列而多次检查同一组点。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-06-26
        • 1970-01-01
        • 1970-01-01
        • 2021-04-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多