Учитывая набор случайных точек в сетке, как вы проверяете эффективно, что все они лежат в фиксированном диапазоне других точек. то есть: выберите любую случайную точку, затем вы сможете перейти к любой другой точке сетки.
Для дальнейшего уточнения: если у вас есть сетка 1000 x 1000 и случайно размещено в ней 100 точек, как вы можете доказать, что любая точка находится в пределах 100 единиц от соседа, и все точки доступны при переходе от одной точки к другой?
Я писал код и обнаружил интересную проблему: очень редко (пока только один раз) он создает остров точек, который превышает максимальный диапазон от остальных точек. Мне нужно исправить эту проблему, но грубая сила, похоже, не решает.
Он написан на Java, но я хорошо разбираюсь либо в псевдокоде, либо в C++.





Небольшая мысль: если вы разделите сетку на патчи 50x50 и разместите начальные точки, вы также запишете, к какому патчу они принадлежат. Теперь, когда вы хотите проверить, находится ли новая точка в пределах 100 пикселей от других, вы можете просто проверить патч плюс 8 окружающих его и посмотреть, совпадают ли подсчеты точек.
Например, вы знаете, что у вас есть 100 случайных точек, и каждый патч содержит количество точек, которые они содержат, вы можете просто просуммировать и посмотреть, действительно ли оно 100 - что означает, что все точки достижимы.
Я уверен, что есть и другие способы, трудные.
Обновлено: расстояние от верхней левой точки до нижнего правого угла патча 50x50 составляет sqrt (50 ^ 2 + 50 ^ 2) = 70 точек, поэтому вам, вероятно, придется выбрать меньший размер патча. Может быть, 35 или 36 (50 ^ 2 = sqrt (x ^ 2 + x ^ 2) => x = 35.355 ...).
Хех, я удивлен, что не подумал об этом, поскольку я использовал рекурсивный алгоритм для получения эффективного распределения по сетке, но когда я выбрал «каплю» в пределах диапазона центральной точки, я начал с линий грубого перебора. сила.
Хм. Я думаю, что ваш метод достаточен, но не необходим - т.е. если он возвращает ИСТИНА, то баллы адекватны, но если он возвращает ЛОЖЬ, то это не означает, что баллы неадекватны.
Найдите выпуклый корпус набора точек, а затем используйте метод вращающиеся суппорты. Две самые удаленные точки на выпуклой оболочке - это две самые удаленные точки в наборе. Поскольку все остальные точки содержатся в выпуклой оболочке, они гарантированно будут ближе, чем две экстремальные точки.
Либо вы неправильно поняли, что мне нужно, либо я неправильно понял, к чему вы клоните. Я не понимаю, как вращающиеся суппорты помогут мне решить мою проблему?
После того, как я перечитал ваш вопрос несколько раз еще раз, оказалось, что я неправильно понял, что вам нужно.
Форсируйте желаемое состояние по конструкции. Вместо того, чтобы размещать все точки исключительно путем рисования случайных чисел, ограничьте координаты следующим образом:
Произвольно разместите начальную точку.
Повторите эти действия для оставшегося количества точек (например, 99):
2.1. Произвольно выберите координату x в некотором диапазоне (например, 90) от предыдущей точки.
2.2. Вычислите допустимый диапазон для координаты y, который будет в пределах 100 единиц от предыдущей точки.
2.3. Произвольно выберите координату Y в этом диапазоне.
Если вы хотите полностью скрыть начало координат, отсортируйте точки по их координатной паре.
Это не потребует больших накладных расходов по сравнению с чистой случайностью, но гарантирует, что каждая точка находится в пределах 100 единиц от хотя бы одной другой точки (фактически, за исключением первой и последней, каждая точка будет в пределах 100 единиц от других точек два).
В качестве варианта вышеизложенного на шаге 2 случайным образом выберите уже сгенерированную точку любой и используйте ее в качестве ссылки вместо предыдущей точки.
Мне нравится подход к строительству @ joel.neely, но если вы хотите обеспечить более однородную плотность, это с большей вероятностью сработает (хотя это, вероятно, даст больше кластера, чем общую однородную плотность):
P_j, которая была размещена ранееP_i, где расстояние (P_i, P_j) <100, повторяя следующее до тех пор, пока действительный P_i не будет выбран в подшаге 4 ниже:
P_i) = координаты (P_j) + (dx, dy).P_i действителен, если он находится внутри общей действующей сетки.Чтобы добавить, на шаге 2 вам не нужно выполнять полный расчет расстояния. Поскольку это в сетке, пройденное расстояние будет просто манхэттенским. | x | + | y |
@ReaperUnreal: на исходном плакате не указывалось, какую метрику он использовал (евклидовую или такси).
Что касается оценки существующих наборов точек, это похоже на проблему типа Евклидово минимальное остовное дерево. На странице википедии указано, что это подграф Триангуляция Делоне; поэтому я думаю, что было бы достаточно вычислить триангуляцию Делоне (см. предыдущую ссылку или "вычислительную геометрию" Google), а затем минимальное остовное дерево и убедиться, что все ребра имеют длину меньше 100.
Из чтения ссылок видно, что это O (N log N), возможно, есть более быстрый способ, но этого достаточно.
Более простой (но, вероятно, менее эффективный) алгоритм будет примерно таким:
j<0 или P[i].x - P[j].x > R, Остановитесь на неудаче. (есть разрыв и все точки не могут быть достигнуты друг от друга с радиусом R)(P[i].x-P[j].x)^2 + (P[i].y-P[j].y)^2 < R ^ 2`, то точка P [i] достижима одной из предыдущих точек в пределах радиуса R, и вернитесь к шагу 4.Обновлено: это можно изменить на что-то, что должен будет O (N log N), но я не уверен:
j<i и координатами x между P [i] .x-R и P [i] .x находятся в наборе YLIST.Новый и улучшенный ;-)
Спасибо Гийому и Джейсону С. за комментарии, которые заставили меня задуматься. Это привело к появлению второго предложения, статистика которого свидетельствует о значительном улучшении.
Гийом заметил, что ранее опубликованная мною стратегия потеряла бы равномерную плотность. Конечно, он прав, потому что это, по сути, «прогулка пьяницы», которая имеет тенденцию вращаться вокруг исходной точки. Однако равномерное случайное размещение точек дает значительную вероятность невыполнения требования «пути» (все точки могут быть соединены путем с шагом не более 100). Проверка на это состояние стоит дорого; генерирование чисто случайных решений до тех пор, пока не будет пройдено, тем более.
Джейсон С. предложил вариант, но статистическое тестирование на большом количестве симуляций привело меня к выводу, что его вариант дает модели, которые так же сгруппированы, как и те, что были в моем первом предложении (на основе изучения среднего и стандартного отклонения значений координат).
Пересмотренный алгоритм ниже создает наборы точек, характеристики которых очень похожи на характеристики чисто (равномерного) случайного размещения, но которые гарантируются конструкцией, чтобы удовлетворить требованию пути. К сожалению, это немного легче визуализировать, чем объяснять устно. Фактически, для этого требуется, чтобы точки случайным образом колебались в неопределенно согласованном направлении (северо-восток, юго-восток, юго-запад, северо-запад), изменяя направление только при "отскоке от стены".
Вот общий обзор:
Выберите случайным образом начальную точку, установите горизонтальное перемещение ВПРАВО и вертикальное перемещение ВНИЗ.
Повторите эти действия для оставшегося количества точек (например, 99 в исходной спецификации):
2.1. Случайным образом выберите dx и dy, расстояние между которыми составляет от 50 до 100. (Я предположил, что евклидово расстояние - квадратный корень из сумм квадратов - в моей пробной реализации, но расстояние «такси» - сумма абсолютных значений - было бы еще проще. кодировать.)
2.2. Примените dx и dy к предыдущей точке на основе горизонтального и вертикального перемещения (ВПРАВО / ВНИЗ -> добавить, ВЛЕВО / ВВЕРХ -> вычесть).
2.3. Если какая-либо координата выходит за границы (менее 0 или не менее 1000), отразите эту координату вокруг нарушенной границы и замените ее перемещение на противоположное направление. Это означает четыре случая (2 координаты x 2 границы):
2.3.1. if x < 0, then x = -x and reverse LEFT/RIGHT horizontal travel.
2.3.2. if 1000 <= x, then x = 1999 - x and reverse LEFT/RIGHT horizontal travel.
2.3.3. if y < 0, then y = -y and reverse UP/DOWN vertical travel.
2.3.4. if 1000 <= y, then y = 1999 - y and reverse UP/DOWN vertical travel.
Обратите внимание, что отражения в шаге 2.3 гарантированно покинут новую точку в пределах 100 единиц от предыдущей точки, поэтому требования к траектории сохраняются. Однако ограничения горизонтального и вертикального перемещения вынуждают генерировать точки случайным образом "перемещаться" по всему пространству, производя более полную дисперсию, чем исходный чистый алгоритм "прогулки пьяницы".
Если я правильно понимаю вашу проблему, учитывая набор сайтов, вы хотите проверить, находится ли ближайший сосед (для расстояния L1, то есть расстояния по сетке) каждого сайта на расстоянии меньше значения K.
Это легко получить для евклидова расстояния путем вычисления триангуляции Делоне множества точек: ближайший сосед сайта является одним из его соседей в триангуляции Делоне. Интересно, что расстояние L1 больше, чем евклидово расстояние (в пределах коэффициента sqrt (2)).
Отсюда следует, что способ проверки вашего состояния заключается в следующем:
Этот алгоритм можно улучшить несколькими способами:
уточняющий вопрос: когда вы говорите «в пределах 100 единиц от соседа», это расстояние по прямой (Евклидово) или расстояние пешком (Манхэттен)?