Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.82/11: Рейтинг темы: голосов - 11, средняя оценка - 4.82
0 / 0 / 0
Регистрация: 03.01.2020
Сообщений: 5

Минимальная сумма растояний между точками

27.01.2024, 22:45. Показов 2023. Ответов 16

Author24 — интернет-сервис помощи студентам
Дано n точек на числовой прямой. Про каждую точку известна ее координата xi.
Расстоянием между точками с координатами x[i] и x[j] будем считать абсолютную разность
их координат: abs(x[i] – x[j]). Точка с координатой x[j] находится ближе к точке x[i], чем точка x[k],
если расстояние между точками x[i] и x[j] меньше, чем между x[i] и x[k].
Требуется выбрать из данных точек точку c наименьшей координатой такую, что сумма
ее расстояний до ближайших к ней k точек наименьшая возможная.
Формат входных данных
В первой строке дано два натуральных числа n и k — число точек и число ближайших
точек, которые надо учитывать (1 ≤ k < n ≤ 10^5).
Во второй строке заданы n целых чисел xi — координаты точек (−10^9 ≤ xi ≤ 10^9).
Формат выходных данных
Выведите два числа — координату выбранной точки и сумму расстояний от нее до
ближайших к ней k точек.
пример 1
ввод
5 2
4 2 3 6 0
вывод
3 2
можно взять число 3, и считать расстояние до 4, тогда разность по модулю равна 1, вторым число 2, разность по модулю 1, в сумме получается 2
пример 2
10 2
4 4 19 2 14 9 11 9 3 20
вывод 4 1
можно взять точку 4, и считать расстояние до 4, тогда разность по модулю будет 0, и до 3 так разность по модулю будет 1, в сумме 2

вот, мой код, у меня неправильный ответ на втором примере
C++ Скопировано
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#include <bits/stdc++.h>
using namespace std;
int main()
{
    long long n, k,mns=100000000000,in=0;
    cin >> n >> k;
    vector<long long> h(n+1);
    for (int i = 1; i <=n; ++i)
        cin >> h[i];
    long long sum=0,sum2=0;
    for(int i=1; i<=n; i++)
    {
        sum=-1;
        sum2=-1;
        if(i-k>=1)
        {
            sum++;
            for(int j=i-k;j<=i;j++)
                sum+=(abs(h[i]-h[j]));
        }
        else if(i+k<=n)
        {
            sum2++;
            for(int j=i;j<=n;j++)
            sum2+=(abs(h[i]-h[j]));
        }
       // cout<<sum<<" "<<sum2<<" "<<i<<endl;
        if(sum<mns and sum>-1)
        {
            mns=sum;
            in=i;
        }
        if(sum2<mns and sum2>-1)
        {
            mns=sum2;
            in=i;
        }
    }
    cout<<h[in]<<" "<<mns;
}
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
27.01.2024, 22:45
Ответы с готовыми решениями:

Найти максимальное и минимальное значение между точками и вывести их вместе с точками
Я уже весь гугл перерыл и всю голову выпотрошил.не получается. Нужно написать функцию для двух массивов х и у. Эти массивы задают...

Минимальная выпуклая оболочка (2D) с условием на расстояние между точками
Всем доброго дня! Столкнулся с проблемой построения МВО для наборов точек сложной (невыпуклой) формы. Кластеризацией я отделяю...

В треугольнике найти точку, сумма растояний от которой до вершин треугольника минимальна
Ребята, помогите с задачкой пожалуйста. Сам недавно начал осваивать С++,а задачка сложная попалась....надо быстро сделать.... Даны...

16
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
12873 / 6737 / 1810
Регистрация: 18.10.2014
Сообщений: 17,057
27.01.2024, 23:10
Цитата Сообщение от ne programer Посмотреть сообщение
вот, мой код
Так а что тут реализовано7 Опишите подробно ваш подход к решению, то есть алгоритм.

Цитата Сообщение от ne programer Посмотреть сообщение
сумма ее расстояний до ближайших к ней k точек
Где у вас в коде определяются "ближайших к ней k точек"? Я что-то в упор этого не увидел.

Я вижу какие-то циклы, назначение которых мне не понятно. Один цикл суммирует расстояния до k точек слева. Другой цикл суммирует расстояния до всех точек справа (то есть тут даже k никак не фигурирует). Что это такое? Что должны делать эти циклы?
0
0 / 0 / 0
Регистрация: 03.01.2020
Сообщений: 5
27.01.2024, 23:14  [ТС]
я сортирую вектор, прохожу понему, и для каждого элемента беру сумму координат от него до i+k(тоесть ближайших k точек), из всего выбираю минимальную сумму
0
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
12873 / 6737 / 1810
Регистрация: 18.10.2014
Сообщений: 17,057
27.01.2024, 23:43
Цитата Сообщение от ne programer Посмотреть сообщение
Требуется выбрать из данных точек точку c наименьшей координатой такую, что сумма
ее расстояний до ближайших к ней k точек наименьшая возможная.
Задача, скорее всего, рассчитана на применение техники "скользящей окрестности". Точки предварительно сортируются по координатам. "Окрестность" - это набор k ближайших точек к текущей точке. При переходе к рассмотрению следующей точки: из "окрестности", возможно, уходит какая-то точка слева и, возможно, добавляется какая-то точка справа. Сумма расстояний при такой операции изменяется (можно пересчитать, но лучше догадаться как сделать без полного пересчета).

Проходим такой "окрестностью" весь массив - находим в итоге минимальную сумму расстояний.

Цитата Сообщение от ne programer Посмотреть сообщение
я сортирую вектор
Так а где в коде сортировка вектора?

Цитата Сообщение от ne programer Посмотреть сообщение
и для каждого элемента беру сумму координат от него до i+k(тоесть ближайших k точек)
Во-первых, что такое "i+k"? Где у вас у коде "сумма координат от него до i+k"? Дайте номера строк.

Во-вторых, с чего вы это взяли, что "ближайшие точки" - это некое "i+k"? Где связь? "Ближайшие" - значит ближайшие по координатам. Они могут лежать как слева, так и справа от точки. Одновременно.
1
 Аватар для nikulin_artyom1
1866 / 2652 / 121
Регистрация: 28.04.2021
Сообщений: 5,981
Записей в блоге: 22
28.01.2024, 00:08
Выводы примеров совпали. Вышло так.
C++ Скопировано
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#include <iostream>
#include <vector>
#include <algorithm>
#include <limits>
 
int main() {
    int n, k;
    std::cin >> n >> k;
    std::vector<int> coordinates(n);
    for (int i = 0; i < n; ++i) {
        std::cin >> coordinates[i];
    }
    //сортировка координат точек
    std::sort(coordinates.begin(), coordinates.end());
    long long minSum = std::numeric_limits<long long>::max();
    int chosenPoint;
    //перебор возможных начальных точек
    for (int i = 0; i <= n - k; ++i) {
        long long currentSum = 0;
        //расчёт суммы расстояний до ближайших k точек
        for (int j = i; j < i + k; ++j) {
            //проверка, чтобы избежать выхода за границы вектора
            if (j < n - 1) {
                currentSum += std::abs(coordinates[j] - coordinates[j + 1]);
            }
        }
        //обновление минимальной суммы и выбранной точки, если текущая сумма меньше
        if (currentSum < minSum) {
            minSum = currentSum;
            chosenPoint = coordinates[i + k / 2];
        }
    }
    std::cout << chosenPoint << " " << minSum << std::endl;
    return 0;
}
2
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
12873 / 6737 / 1810
Регистрация: 18.10.2014
Сообщений: 17,057
28.01.2024, 01:07
Цитата Сообщение от nikulin_artyom1 Посмотреть сообщение
C++ Скопировано
1
2
        //расчёт суммы расстояний до ближайших k точек
        for (int j = i; j < i + k; ++j) {
"Cуммой расстояний до ближайших k точек" для какой точки?

Более того, не ясно, зачем вообще понадобился такой цикл, если очевидно, что вычисляемая им сумма заведомо равна coordinates[i+k] - coordinates[i]? И никакого цикла не нужно.

Цитата Сообщение от nikulin_artyom1 Посмотреть сообщение
chosenPoint = coordinates[i + k / 2];
Почему эти k точек будут являться "ближайшими k" для точки i + k / 2?

Цитата Сообщение от nikulin_artyom1 Посмотреть сообщение
Выводы примеров совпали.
Только потому, что примеры приведены для непоказательного случая k=2. "Сумма расстояний" - это сумма расстояний от точки до всех остальных точек, а не сумма попарных расстояний между соседями в группе. То есть ваш цикл вычисляет совсем не ту сумму вообще.
1
 Аватар для nikulin_artyom1
1866 / 2652 / 121
Регистрация: 28.04.2021
Сообщений: 5,981
Записей в блоге: 22
28.01.2024, 01:09
TheCalligrapher, я делал, чтобы прийти к результатам данных примеров
0
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
12873 / 6737 / 1810
Регистрация: 18.10.2014
Сообщений: 17,057
28.01.2024, 01:10
Цитата Сообщение от nikulin_artyom1 Посмотреть сообщение
я делал, чтобы прийти к результатам данных примеров
??? То есть на само условие задачи вы вообще не смотрели?
0
случайный прохожий
 Аватар для gunslinger
3170 / 2184 / 638
Регистрация: 20.07.2013
Сообщений: 5,848
28.01.2024, 02:31
Цитата Сообщение от TheCalligrapher Посмотреть сообщение
Точки предварительно сортируются по координатам.
А как (быстро) сортировать такое количество точек (порядка 105)?
Процесс наверняка займет какое-то (возможно, критичное) время.
Хотя ввод данных (вручную) тоже процесс не быстрый (если это влияет на результат).
1
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
12873 / 6737 / 1810
Регистрация: 18.10.2014
Сообщений: 17,057
28.01.2024, 10:12
Моя попытка реализовать именно то, о чем я вел речь в #4. Получилось эффективно, но в коде несколько более громоздко, чем я ожидал. Возможно что есть более простое решение

C++ Скопировано
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
#include <cassert>
#include <cstdlib>
#include <vector>
#include <algorithm>
#include <iostream>
 
struct State
{
  using XS = std::vector<int>;
  XS &xs;
  unsigned i; // текущая точка
  unsigned il, ir; // [il, ir] - k-окрестность
  unsigned sum; // текущая сумма расстояний
 
  State(XS &xs, unsigned k) : xs(xs), i(0), il(0), ir(k)
  {
    std::sort(xs.begin(), xs.end());
    sum = sum_k();
  }
 
  unsigned sum_k() const 
  { // Эта функция используется только один раз - при инициализации
    // Все остальные вызовы делаются изнутри `assert`
    // По техническим причинам допускается, что i находится за пределами [il, ir]
    assert(i < xs.size());
    assert(il < ir && ir < xs.size());
 
    unsigned sum = 0;
    for (unsigned j = il; j <= ir; ++j)
      sum += std::abs(xs[j] - xs[i]);
 
    return sum;
  }
 
  void shift_lr()
  { // По техническим причинам допускается, что i находится за пределами [il, ir]
    assert(i < xs.size());
    assert(il < ir && ir < xs.size());
 
    ++il, ++ir;
    sum += std::abs(xs[ir] - xs[i]);
    sum -= std::abs(xs[il - 1] - xs[i]);
 
    assert(sum == sum_k());
  }
 
  bool shift_i()
  {
    assert(il < ir && ir < xs.size());
    assert(il <= i && i <= ir);
 
    if (++i == xs.size())
      return false;
 
    // Здесь i мог выйти за [il, ir]
    // Все равно исправяляем сумму для нового i
 
    assert(xs[i - 1] <= xs[i]);
    unsigned delta = xs[i] - xs[i - 1];
    assert(il < i && i - 1 <= ir);
    unsigned nl = i - il, nr_old = ir - (i - 1);
    sum += delta * nl;
    assert(sum >= delta * nr_old);
    sum -= delta * nr_old;
 
    assert(sum == sum_k());
 
    // ... а затем исправляем ситуацию с [il, ir]
 
    assert(il < i && i <= ir + 1);
    if (i > ir)
      shift_lr();
 
    assert(il < i && i <= ir);
    return true;
  }
 
  void minimize()
  { // Сдвигаем [il, ir] пока это уменьшает сумму
    assert(il <= i && i <= ir);
    for (; il < i && ir + 1 < xs.size(); shift_lr())
    { // il - кандидат на выход, ir + 1 - кандидат на вход в окрестность
      assert(xs[il] <= xs[i] && xs[i] <= xs[ir + 1]);
      unsigned delta_l = xs[i] - xs[il], delta_r = xs[ir + 1] - xs[i];
      if (delta_r >= delta_l)
        break;
    }
  }
};
 
int main() 
{
  unsigned n = 0, k = 0;
  std::cin >> n >> k;
 
  State::XS xs(n);
  for (int &x : xs)
    std::cin >> x;
 
  State s(xs, k);
  unsigned min_sum = s.sum, min_i = s.i;
 
  while (s.shift_i())
  {
    s.minimize();
 
    if (s.sum < min_sum)
    {
      min_sum = s.sum;
      min_i = s.i;
    }
  }
 
  std::cout << xs[min_i] << " " << min_sum << std::endl;
}
Добавлено через 4 часа 29 минут
Цитата Сообщение от gunslinger Посмотреть сообщение
А как (быстро) сортировать такое количество точек (порядка 105)?
105 - это, вообще-то, детский сад. Сортировать обычным алгоритмом сортировки.

Смысл задачи - найти способ избежать циклов длины k при обработке каждой из n точек. Если делать так, то будет вылет за ограничения по времени. И по сравнению с этой тормознёй сортировка 105 точек - это мелочи.
3
случайный прохожий
 Аватар для gunslinger
3170 / 2184 / 638
Регистрация: 20.07.2013
Сообщений: 5,848
28.01.2024, 19:52
TheCalligrapher, позволю себе включить "режим старого деда".
Возьмем гипотетическую ситуацию - "простая" сортировка 105 элементов через двойной цикл требует примерно 1010 операций (сравнения), не считая "перестановку" элементов.
Тогда "простая" (без оптимизации) проверка (всех) k соседних точек для n точек (для отсортированного массива) потребует примерно (если не ошибаюсь) n * (k + 1) операций (или n * k * (k + 1) ? - тогда вопрос снимается), то есть количество того же порядка (или на порядки больше ?). С оптимизацией кол-во будет меньше (но тут мне сложно посчитать).
Для сортировки есть sort. Допустим, нет этой функции (или метода, название не имеет значения). Тогда нам пришлось бы и сортировку оптимизировать.
То есть две эти части задачи (теоретически) также сравнимы (если нет разницы на порядки) по необходимости оптимизации.
Я прав или несу полную чушь?

И еще. В этой теме ничего не сказано про то, что 105 элементов - это много (касаемо памяти).
При этом есть фраза
Цитата Сообщение от TheCalligrapher Посмотреть сообщение
поместилось ли бы это в локальную память при N = 1000?
Там это 106 элементов (момент, что в той задаче массив не нужен, опустим). Неужели разница настолько сильная (вроде всего 10-кратная)?

Благодарю за внимание.
0
Нарушитель
Эксперт функциональных языков программированияЭксперт С++
4514 / 2400 / 987
Регистрация: 01.06.2021
Сообщений: 8,294
28.01.2024, 20:15
Кто-нибудь знает, что за олимпиада: https://rsr-olymp.ru/upload/fi... -21-22.pdf ? Задание взято отсюда.
0
случайный прохожий
 Аватар для gunslinger
3170 / 2184 / 638
Регистрация: 20.07.2013
Сообщений: 5,848
28.01.2024, 23:06
Royal_X, да хз.

Насчет решения задачи - у меня вроде "что-то" получилось (через функцию; дополнительно см. комментарии в коде).
Насчет ошибок не знаю, проверял только на тестовых значениях.
Но логика должна быть верна, если нигде не напортачил.

Код:
C++ Скопировано
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
int coord (int n, int k, int *x, unsigned long long &dist)
{
  // 1 ≤ k < n ≤ 10^5
  // −10^9 ≤ xi ≤ 10^9
 
  int i, j, tmp, point_x, count;
  unsigned long long sum;
 
  // заполнение массива (через ГПСЧ) - для тестов и прочего
  // int num = 1e9;
  // for (i = 0; i < n; i++)
  //   x[i] = rand() % (2 * num + 1) - num;
 
  // сортировка (простая)
  for (i = 0; i < n - 1; i++)
    for (j = i + 1; j < n; j++)
      if (x[j] < x[i])
      {
        tmp = x[j];
        x[j] = x[i];
        x[i] = tmp;
      }
 
  // считаем сумму расстояний для точки x[0]
  sum = 0;
  point_x = x[0];
  for (i = 1; i <= k; i++)
    sum += x[i];
  sum -= k * x[0];
  dist = sum;
  if (dist == 0)
    return point_x;
 
  // проход по точкам и окрестностям
  // наверно можно оптимизировать подсчет расстояний не только
  // при проверке (всех) точек окрестности для текущей точки x[i],
  // но и когда еще меняется точка x[i], но тут я пас
  for (i = 0; i < n; i++)
  {
    sum = 0;
    count = 0;
 
    for (j = i - k; j <= i + k; j++)
      if (j != i && j >= 0 && j < n)
      {
        count++;
 
        sum += abs(x[i] - x[j]);
 
        if (count > k)
        {
          count--;
          tmp = (j == i + k) ? j - k : j - k - 1;
          sum -= abs(x[i] - x[tmp]);
        }
 
        if (count == k  && sum < dist)
        {
          dist = sum;
          point_x = x[i];
 
          if (dist == 0)
            return point_x;
        }
      }
  }
 
  return point_x;
}
Пример использования:
C++ Скопировано
1
2
3
4
5
6
7
8
9
  const n = 10;
  int k = 2, x[n] = {4, 4, 19, 2, 14, 9, 11, 9, 3, 20};
  unsigned long long dist;
 
  // выводим значение координаты (x[i]):
  // coord(n, k, x, dist)
 
  // выводим сумму расстояний:
  // dist
1
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
12873 / 6737 / 1810
Регистрация: 18.10.2014
Сообщений: 17,057
30.01.2024, 05:07
Несколько другой подход: на основе другого классического приема - предварительное вычисление всех частичных сумм.

Заранее отсортируем массив координат, а затем заранее подготовим массив sums[], который каждой точке i (индекс) сопоставляет сумму расстояний от нее до всех точек слева от нее (вплоть до самой левой). Такой массив легко строится инкрементально в один проход слева-направо.

Тогда пользуясь этим массивом мы сможем мгновенно вычислять сумму расстояний sum_left(j, i) от точки i до точек слева от нее в диапазоне индексов [j, i] (j < i):
sum_left(j, i) := sums[i] - sums[j] - (xs[i] - xs[j]) * j
А также, пользуясь этим же массивом, мы сможем мгновенно вычислять сумму расстояний sum_right(i, j) от точки i до точек справа от нее в диапазоне индексов [i, j] (j > i):
sum_right(i, j) := (xs[j] - xs[i]) * (j - i + 1) - sum_left(i, j)
Пользуясь этими двумя функциями мы можем мгновенно вычислять сумму расстояний от любой точки i до ее соседей в диапазоне [il, il+k].

В остальном алгоритм остается тем же: последовательно анализируем точки массива и одновременно двигаем по массиву "окно" шириной в k+1 точек. После того, как мы увеличили индекс текущей точки i, нам может лишь понадобиться сдвинуть диапазон [il, il+k] вправо в поиске нового минимума.

То есть в моей предыдущей реализации текущее значение суммы постоянно поддерживалось инкрементально, путем вычитания из суммы расстояния до уходящей из окрестности точки и добавления в сумму расстояния до приходящей в окрестность точки (а также, разумеется, сумму нужно было инкрементально обновлять и при увеличении индекса i). В этой реализации мы, выполнив препроцессинг, имеем возможность просто мгновенно получать требуемую сумму для любой точки и любой окрестности, поэтому постоянная инкрементальная поддержка суммы становится ненужной

C++ Скопировано
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
#include <cassert>
#include <vector>
#include <algorithm>
#include <iostream>
 
int main() 
{
  unsigned n = 0, k = 0;
  std::cin >> n >> k;
 
  std::vector<int> xs(n);
  for (int &x : xs)
    std::cin >> x;
 
  std::sort(xs.begin(), xs.end());
 
  std::vector<unsigned long long> sums(n);
  for (unsigned i = 1; i < n; ++i)
    sums[i] = sums[i - 1] + (unsigned long long) (xs[i] - xs[i - 1]) * i;
 
  auto sum_left = [&](unsigned il, unsigned i)
  {
    assert(il <= i && i < xs.size());
    assert(xs[il] <= xs[i] && sums[il] <= sums[i]);
    unsigned long long raw_sum = sums[i] - sums[il];
    unsigned long long excess_sum = (unsigned long long) (xs[i] - xs[il]) * il;
    assert(excess_sum <= raw_sum);
    return raw_sum - excess_sum;
  };
 
  auto sum_right = [&](unsigned i, unsigned ir)
  {
    assert(i <= ir && ir < xs.size());
    assert(xs[i] <= xs[ir]);
    unsigned long long full_sum = (unsigned long long) (xs[ir] - xs[i]) * (ir - i + 1);
    unsigned long long complementary_sum = sum_left(i, ir);
    assert(complementary_sum <= full_sum);
    return full_sum - complementary_sum;
  };
 
  auto sum_k = [&, k](unsigned il, unsigned i)
    { return sum_left(il, i) + sum_right(i, il + k); };
 
  unsigned i = 0, il = 0;
  unsigned long long sum = sum_k(il, i);
  // Сумма для точек в диапазоне [il, il+k] относительно i
 
  unsigned min_i = i;
  unsigned long long min_sum = sum;
 
  for (++i; i < n; ++i)
  {
    // Проверим, что i не вышло за [il, il+k]
    if (il + k < i)
      ++il;
 
    assert(il <= i && il + k >= i);
 
    sum = sum_k(il, i);
    // Сумма для текущего [il, il+k]
 
    // Сдвигаем дипазон [il, il+k] вправо, пока это уменьшает сумму
    for (; il < i && il + 1 + k < xs.size(); ++il)
    {
      unsigned long long next_sum = sum_k(il + 1, i);
      if (next_sum >= sum)
        break;
 
      sum = next_sum;
    }
 
    if (sum < min_sum)
    {
      min_sum = sum;
      min_i = i;
    }
  }
 
  std::cout << xs[min_i] << " " << min_sum << std::endl;
}
Также можно заметить, что выполненный препроцессинг не зависит от значения k, то есть выполнив такой препроцессинг один раз, задачу затем можно эффективно решать много раз на одних и тех же входных данных, но для разных значений k.
2
случайный прохожий
 Аватар для gunslinger
3170 / 2184 / 638
Регистрация: 20.07.2013
Сообщений: 5,848
30.01.2024, 09:59
Решение отличное.

И имеется следующая идея (возможно, бредовая). Если использовать не сумму расстояний до всех точек слева от x[i], а, например, сумму всех элементов слева от x[i] или (что, наверно, лучше) значения x[i] - x[i - 1] ?

Как вариант данных (для понимания идеи):
Code Скопировано
1
2
3
4
5
6
7
4 4 19 2 14 9 11 9 3 20 - исходный массив
 
2 3 4 4 9 9 11 14 19 20 - отсортированный
 
0 1 1 0 5 0  2  3  5  1 - значения y[i] = x[i] - x[i - 1] (y[0] приравниваем к 0 или x[0])
 
0 2 5 9 13 22 31 42 56 75 - сумма всех элементов слева от x[i]
Можно каким-либо образом применить подобные предварительные вычисления? Или это все "фантазии"?
0
случайный прохожий
 Аватар для gunslinger
3170 / 2184 / 638
Регистрация: 20.07.2013
Сообщений: 5,848
30.01.2024, 17:47
Немного подумал и пришел к выводу, что способ решения через использование значений y[i] = x[i] - x[i - 1] является не очень оптимальным (про сумму всех элементов слева от x[i] вообще молчу - большой вопрос, как это вообще использовать). "Локально" (в статике) вариант (через y[i]) достаточно простой, но при движении по окрестности точки x[i] (не говоря уж про изменение точек x[i]) потребуется либо применять (полный) пересчет "сумм расстояний до точек окрестности", либо убирать левую точку с добавлением правой через кучу операций.
Так что идея оказалась совсем не жизнеспособной. А выглядело все весьма заманчиво... (жизнь - боль ).
0
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
12873 / 6737 / 1810
Регистрация: 18.10.2014
Сообщений: 17,057
31.01.2024, 00:06
Цитата Сообщение от gunslinger Посмотреть сообщение
сумму всех элементов слева от x[i] или (что, наверно, лучше) значения x[i] - x[i - 1] ?
Я не вижу смысл в предварительном вычислении "дешевых" характеристик, вроде x[i] - x[i - 1]. Зачем это предварительно вычислять, если эта величина и так вычисляется мгновенно?

Если решение на основе таких тривиальных характеристик существует, то оно будет в первую опираться на какое-то пока мне неизвестное свойство задачи. Именно это свойство и надо искать. А x[i] - x[i - 1] тут ничего не меняет.

Добавлено через 2 часа 53 минуты
Цитата Сообщение от gunslinger Посмотреть сообщение
(про сумму всех элементов слева от x[i] вообще молчу - большой вопрос, как это вообще использовать
Как раз таки это можно использовать. В моем решении в #14 массив sum[] определяется как
https://www.cyberforum.ru/cgi-bin/latex.cgi?sum[j] = \sum_{i=0}^{j}(x[j]-x[i])
что эквивалентно
https://www.cyberforum.ru/cgi-bin/latex.cgi?sum[j] = x[j]*(j + 1) - \sum_{i=0}^{j}\, x[i]
Вычитаемое - именно ваша сумма. Произведение x[j]*(j+1) вычисляется "мгновенно", то есть можно считать, что использованная мною сумма фактически эквивалентна предложенной вами.
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
31.01.2024, 00:06
Помогаю со студенческими работами здесь

Поставить точку D на оси Х так, чтобы сумма растояний от точек А, В, С была минимальной
помогите исправить ошибку. Программа сама работает,но я не знаю как сравнивать расстояние. На координатной плоскости x и y даны три точки...

Минимальная сумма расстояний между каждым элементом массива и множествами из К-элементов этого массива
Всем привет! Еще одна модификация одной из самых распространённых задач. (Минимальная сумма абсолютных разностей между элементом и...

Минимальная сумма расстояний между каждым элементом массива и множествами из к-элементов этого массива
Всем привет. Еще одна модификация одной из самых распространённых задач. (Минимальная сумма абсолютных разностей между элементом и...

На плоскости заданы 2n точек. Объединить их в пары так, чтобы сумма всех расстояний между точками была миниальной
На плоскости заданы 2n точек. Объединить их в пары так, чтобы сумма всех расстояний между точками была миниальной. Была такая идея...

Установить биекцию между точками эллипса и точками окружности
Установить биекцию между точками эллипса x^2/4+y^2/9= 1 и точками окружности x^2+y^2=16.


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
17
Ответ Создать тему
Новые блоги и статьи
Работа с объемным DOM в javascript
Htext 04.04.2025
Сегодня прочитал статью тут о расходах памяти в JS, ее утечках и т. п. И вот что вспомнил из своей недавней практики. Может, кому пригодится. Хотя, в той статье об этом тоже есть. Дело в том, что я. . .
Оптимизация производительности Node.js с помощью кластеризации
run.dev 04.04.2025
Масштабирование приложений для обработки тысяч и миллионов запросов — обыденная задача для многих команд. Node. js, благодаря своей асинхронной событийно-ориентированной архитектуре, стал популярной. . .
Управление зависимостями в Python с Poetry
py-thonny 04.04.2025
Стандартный инструмент для установки пакетов в Python - pip - прекрасно справляется с базовыми сценариями: установил пакет командой pip install и используешь его. Но что произойдёт, когда разные. . .
Мониторинг с Prometheus в PHP
Jason-Webb 04.04.2025
Prometheus выделяется среди других систем мониторинга своим подходом к сбору и хранению метрик. В отличие от New Relic, который использует агентный подход и отправляет данные во внешнее хранилище,. . .
Пакет Context в Golang: Управление потоками и ресурсами
golander 04.04.2025
Работа с горутинами в Go часто напоминает управление непослушными детьми - они разбегаются кто куда, делают что хотят и не всегда завершаются вовремя. К счастью, в Go 1. 7 появился пакет context,. . .
Контейнеризация React приложений с Docker
Reangularity 03.04.2025
Контейнеризация позволяет упаковать приложение со всеми его зависимостями в автономный контейнер, который можно запустить на любой платформе с установленным Docker. Это существенно упрощает процессы. . .
Свой попап в SwiftUI
mobDevWorks 03.04.2025
SwiftUI, как декларативный фреймворк от Apple, предоставляет множество инструментов для создания пользовательских интерфейсов. В нашем распоряжении есть такие API как alerts, popovers, action sheets. . .
Антипаттерны микросервисной архитектуры
ArchitectMsa 03.04.2025
Хорошо спроектированная микросервисная система может выдержать испытание временем, оставаясь гибкой, масштабируемой и устойчивой к большинству проблем. Такая архитектура обладает высоким уровнем. . .
std::mutex в C++: Советы и примеры использования
bytestream 03.04.2025
std::mutex - это механизм взаимного исключения, который гарантирует, что критический участок кода выполняется только одним потоком в каждый момент времени. Это простое, но могущественное средство. . .
Не удержался от оценки концепции двигателя Стирлинга.
Hrethgir 03.04.2025
Сколько не пытался - она выдавала правильные схемы, причём случайно рисовала горячие области в середине, холодные по краям, трубки с краёв в низ и магнит в соединяющей, но при этой выдавала описание. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru
Выделить код Копировать код Сохранить код Нормальный размер Увеличенный размер