Найти количество прямоугольников из заданного набора координат

Мне нужно найти максимальное количество прямоугольников из заданного набора координат.

Рассмотрим следующие координаты, заданные в системе координат 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 сек.

Спасибо


person Alin    schedule 05.10.2013    source источник
comment
Решите, в чем вопрос. 4 точки образуют прямоугольник или сколько прямоугольников можно составить из заданных точек?   -  person hasan    schedule 06.10.2013
comment
Оба они на самом деле, как я могу проверить, что 4 точки образуют прямоугольник и как я могу найти максимальное количество возможных прямоугольников   -  person Alin    schedule 06.10.2013
comment
Это вопрос АКМ?   -  person hasan    schedule 06.10.2013
comment
Не ACM, из книги с практическими вопросами   -  person Alin    schedule 06.10.2013
comment
каково максимальное количество баллов?   -  person hasan    schedule 06.10.2013
comment
все заданные точки являются целыми числами?   -  person hasan    schedule 06.10.2013
comment
Каковы максимальные значения x и y   -  person hasan    schedule 06.10.2013
comment
ответ на все эти вопросы даст другое решение   -  person hasan    schedule 06.10.2013
comment
пожалуйста, попробуйте ответить на мои вопросы, чтобы я мог дать вам наиболее подходящее решение для ситуации.   -  person hasan    schedule 06.10.2013


Ответы (6)


Для каждой пары точек, скажем, (x1, y1) и (x2, y2), считайте ее диагональю некоторого прямоугольника. Если в исходном множестве есть точки (x1, y2) и (x2, y1), то мы нашли наш прямоугольник. Следует отметить, что будут существовать 2 диагонали, которые будут представлять один и тот же прямоугольник, поэтому мы делим окончательный ответ на 2.

Это будет работать только для прямоугольников, параллельных оси x или оси y.

Псевдокод С++:

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;
person Anurag Singh    schedule 30.09.2019
comment
помогите мне здесь. является (1,1) (2,2) (3,1) (2,0) прямоугольником? - person hasan; 07.10.2019
comment
@hasan - это прямоугольник, но его стороны не параллельны осям координат - person Anurag Singh; 21.10.2019

Разделите свои точки в списках координаты «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.

person Eneko Alonso    schedule 28.10.2013
comment
Удивительно, я изо всех сил пытался найти способ добиться этого - person AlvaroAV; 06.03.2016
comment
Я только что увидел вашу заметку об ортогонале. прости - person hasan; 07.10.2019
comment
Однако должен быть способ поворота после ортогонального случая. Просто изменив расчет координат. - person John LaBarge; 15.02.2020

Чтобы проверить, образуют ли 4 точки прямоугольник:

  1. для каждых двух точек рассчитайте расстояние. хранить все в массиве поплавков.
  2. отсортировать массив.

у вас будет a[0] = a[1], a[2] = a[3], a[4] = a[5]

person hasan    schedule 05.10.2013
comment
Ваше условие необходимо, но недостаточно: a parallelorgram также подойдет. А сравнивать числа с плавающей запятой на точное равенство — плохая идея из-за ошибок округления. - person MvG; 06.10.2013
comment
Я немного озадачен этим решением. Как насчет этого набора точек (a,b,c,d) = (1,2),(2,1),(3,1),(4,2) Расстояние между a и b такое же, как расстояние между c и d, но они не образуют прямоугольник. - person Eneko Alonso; 29.10.2013
comment
у вас должно быть шесть значений. a-b = c-d, a-d = b-c, a-c = b-d. последний - диагонали. - person hasan; 29.10.2013
comment
Но если бы у вас был гораздо более длинный список точек, скажем, 100, как бы вы нашли 3 пары расстояний, необходимых для прямоугольника между 10k парами расстояний? - person Eneko Alonso; 29.10.2013
comment
Я прокомментировал вышеуказанный вопрос с большим количеством вопросов. Мне нужно много информации, чтобы найти подходящее решение для каждой ситуации. ответь на них, и я скажу тебе. - person hasan; 29.10.2013
comment
Итак, ваш ответ только проверяет, является ли набор из 4 точек прямоугольником или нет, но не решает проблему, как найти количество прямоугольников на конечном наборе точек. Я обвиняю автора вопроса в том, что он задал два разных вопроса: P - person Eneko Alonso; 29.10.2013
comment
Я собирался продолжить редактирование, чтобы ответить на полный вопрос. но он не отредактировал свой вопрос и не ответил на мои вопросы. поэтому он действительно не знал, какая у него входная спецификация. так что ответ его удовлетворил. ты собираешься ответить на эти вопросы? - person hasan; 29.10.2013
comment
@Mvg никакой параллелограмм не удовлетворяет. Я думал, что ответил на это! a[4] != a[5] в параллелограммах - person hasan; 17.04.2020

Как я могу найти, образуют ли следующие координаты прямоугольник

Проверьте, являются ли разностные векторы ортогональными, т.е. имеют нулевое скалярное произведение.

Это не проверяет, включены ли эти координаты в ваш список. Он также не проверяет, выровнен ли прямоугольник с осями координат, что было бы гораздо более простой задачей.

Если вы хотите найти все прямоугольники во входных данных, вы можете выполнить описанную выше проверку для всех четверок. Если это неприемлемо по соображениям производительности, вам следует обновить свой вопрос, указав, с каким размером проблемы и ограничениями производительности вы сталкиваетесь.

person MvG    schedule 05.10.2013
comment
Если я правильно понял, ваше предложение состоит в том, чтобы перебрать все четверки точек (O(n^4)) и проверить, является ли v . w = 0 для каждой четверки, где v = p1-p2 и w = p3-p4, верно? Что именно вы имеете в виду под этим не проверяет, включены ли эти координаты в ваш список? Вы перебираете заданные точки, так зачем вам эта проверка? - person Alan Evangelista; 03.12.2019

Моя скромная покорность

введите здесь описание изображения

Я предполагаю, что количество оптимизаций возможно.

person Chef Gladiator    schedule 28.01.2020

Мой подход заключается в

  • Пройтись по каждой точке
  • Проверьте, какие все точки находятся прямо над этой точкой, а затем сохраните координаты 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))
person pkd    schedule 14.03.2021