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

Это задача с польской олимпиады по информатике под названием Pionek (PIO).

Учитывая набор неуникальных векторов, найдите максимально возможное евклидово расстояние относительно точки (0,0), которого вы можете достичь, перемещаясь с использованием векторов из набора. Каждый вектор можно использовать только один раз. Вернуть квадрат найденного расстояния.

  1. Мы знаем, что для каждого вектора [x, y] из множества 10^-4 <= x,y <= 10^4

  2. Для n, количества векторов в наборе, неравенство n <= 200 000 выполняется

  3. Ограничение памяти 128MB

Пример ввода:

5 -> number of vectors
2 -2 -> [x, y] vector
-2 -2
0 2
3 1
-3 1

Наилучшего результата мы добьемся, выбрав векторы [0,2], [3,1], [2, -2]. Нашей конечной точкой назначения будет (5, 1), поэтому квадрат евклидова расстояния от (0,0) до (5,1) равен 26, и это действительный результат для этого ввода.

Я написал ниже решение грубой силы:

#include <iostream>
#include <vector>

using namespace std;

long long solve(const vector<pair<int, int>>& points, int i, int x, int y) {
    if (i == points.size())
        return 1LL * x * x + 1LL * y * y;

    long long ans = 0;
    ans = max(solve(points, i + 1, x, y), solve(points, i + 1, x + points[i].first, y + points[i].second));
    return ans;
}

int main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);

    int n;
    cin >> n;

    vector<pair<int, int>> points(n);
    for (int i = 0; i < n; ++i)
        cin >> points[i].first >> points[i].second;

    cout << solve(points, 0, 0, 0);
}

Конечно, это слишком медленно (большинство тестовых случаев требуют времени выполнения менее 0,5 с или менее 1,5 с). Я могу использовать мемоизацию, но тогда превышаю лимит памяти.

За исключением грубой силы, я понятия не имею, что я могу сделать. Как мы можем решить ее с приемлемой временной сложностью, например O(nlogn)?

Сначала отсортировать?!!!?

user24714692 09.06.2024 20:32

Было бы полезно, если бы вы описали, что вы подразумеваете под «грубой силой», потому что иногда это не совсем понятно.

Ulrich Eckhardt 09.06.2024 20:36

@UlrichEckhardt Представленное здесь решение методом грубой силы просто пробует все подмножества векторов.

Unmitigated 09.06.2024 20:38

Сравните решение методом грубой силы с суммой всех векторов. (Я ожидаю, что он будет в том же полупространстве.)

greybeard 09.06.2024 20:39

@AhmedAEK Эта проблема была из конкурса (поэтому она, безусловно, разрешима), и существует четкое решение O (N log N).

Unmitigated 09.06.2024 21:18

Обратите внимание: хотя это и очевидно, но для любого набора векторов конечная точка одинакова для всех упорядочений этих векторов.

Cary Swoveland 10.06.2024 00:02
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
5
6
117
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

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

Более детально:

  1. Вы сортируете все векторы так, чтобы их угол увеличивался. atan2() поможет вам в этом.
  2. Вы берете первый вектор, а затем добавляете все последующие векторы, пока конечный результат не уменьшится в длине. Выбранные вами векторы будут иметь угол до 180 градусов. Если этот частичный результат лучше предыдущего, вы сохраняете индексы как результат.
  3. Поверните последовательность векторов так, чтобы первый был последним, а второй первым.
  4. Повторяйте шаг 2, пока не выполните полный поворот всех векторов.

Это, конечно, еще не оптимально. Чтобы улучшить его, вы не поворачиваете векторы (требуется много копий), а просто получаете к ним доступ по кругу (применяете оператор по модулю к индексу). Далее вы используете скользящее окно над векторами. Это означает, что как только вы достигли оптимального конечного вектора для определенного начального вектора (чтобы получить один результат), вы удаляете начальный вектор из суммы для следующего раунда. Это позволяет избежать сложения всех векторов, по которым два окна перекрываются.

Кстати: если реализовано с двумя дополнительными хаками, это должно работать за время O(n log n) и пространство O(1). Обоснование для времени: во-первых, сортировку можно выполнить за O(n log n). Затем для первого окна вы добавляете в среднем O(n/2) векторов. Затем для каждого из остальных n-1 окон каждый вектор будет добавлен один раз и удален один раз (в среднем O(1)), что составит O(n). Обоснование использования пространства: вы сохраняете только лучший результат, используя один вектор и два индекса для окна.

Другие вопросы по теме