У похід!#11059

У похід! (Розбір)

Нехай Смішарик знаходиться в точці . Тоді за секунд він зможе опинитися в будь-якій цілочисельній точці ромбу, як показано на рисунку.

Потрібно знайти найменше натуральне , при якому всі ромби відповідного розміру для кожного Смішарика матимуть хоча б одну спільну цілочисельну точку. Розглянемо третій тест і зобразимо ромби для трьох Смішариків при t = 1, 2, 3.

При t = 3 смішарики, наприклад, можуть зустрітися в точці або .

Обертаймо систему координат на відносно початку координат. При такому перетворенні ромби перетворяться у квадрати. Виведемо формули обертання:

z' = ze^{-i\frac{\pi}{4}}

Або в декартових координатах:

x' + iy' = (x + iy) \cdot (\cos\left(\frac{\pi}{4}\right) - i\sin\left(\frac{\pi}{4}\right))
\begin{cases} x' = x\frac{\sqrt{2}}{2} + y\frac{\sqrt{2}}{2} \\ y' = -x\frac{\sqrt{2}}{2} + y\frac{\sqrt{2}}{2} \end{cases}

Позбудемося ірраціональності, розтягнувши зображення в \sqrt{2} рази. Для цього скористаємося наступним перетворенням:

\begin{cases} x' = x + y \\ y' = -x + y \end{cases}

Преобразуємо наші три точки:

Знайдемо координати прямокутника, що містить усі точки (x_i', y_i') — перетворені початкові координати смішариків. Позначимо:

Тоді прямокутник з протилежними кутами (min_x, min_y) та (max_x, max_y) містить усі точки (x_i', y_i'). При цьому він є мінімальним за площею прямокутником, сторони якого паралельні осям координат.

У нашому прикладі таким прямокутником буде (0, 0) - (6, 3).

Точкою збору смішариків (res_x, res_y) буде центр цього прямокутника, тобто точка з координатами

(res_x, res_y) = \left(\frac{min_x + max_x}{2}, \frac{min_y + max_y}{2}\right)

Тепер потрібно знайти мінімальний час, за який усі Смішарики зможуть дістатися з їхніх точок (x_i', y_i') до точки (res_x, res_y). Для повернутого ромба (квадрата в новій системі координат) відстань від точки (x_i', y_i') до (res_x, res_y) обчислюється за формулою:

max( | x_i' - res_x |, | y_i' - res_y |)

Таким чином, усі Смішарики зможуть зібратися в точці (res_x, res_y) за час, рівний максимальному з цих відстаней:

\max_{1 \le i \le n}\left( max( | x_i' - res_x |, | y_i' - res_y |) \right)

Реалізація алгоритму

Оголосимо константу нескінченність .

typedef long long ll;
#define INFL (ll)4e18

Вхідні точки будемо зберігати в масиві .

vector<pair<ll, ll>> inp;

Функція calc обчислює відстань від точки до найвіддаленішого Смішарика. Перетворені координати Смішариків знаходяться в масиві .

ll calc(ll x, ll y)
{
  ll res = 0;
  for (auto p : inp)
    res = max(res, max(abs(p.first - x), abs(p.second - y)));
  return res;
}

Основна частина програми. Читаємо вхідні дані.

cin >> n;
minx = INFL; maxx = -INFL; miny = INFL; maxy = -INFL;
for (i = 0; i < n; i++)
{

Читаємо вихідні координати Смішарика . Виконуємо поворот координатної площини на і зберігаємо отримані координати в масиві .

  cin >> x >> y;
  nx = x + y;
  ny = -x + y;
  inp.push_back({ nx, ny });

Після цього знаходимо координати прямокутника з протилежними кутами (min_x, min_y) і (max_x, max_y), який містить усі точки (x_i', y_i') — перетворені координати Смішариків.

  minx = min(minx, nx);
  maxx = max(maxx, nx);
  miny = min(miny, ny);
  maxy = max(maxy, ny);
}

Визначаємо точку збору Смішариків (res_x, res_y) — центр прямокутника.

resx = (minx + maxx) / 2;
resy = (miny + maxy) / 2;

Обчислюємо і виводимо мінімальний час, необхідний для того, щоб усі Смішарики змогли дістатися з їхніх точок (x_i', y_i') до точки (res_x, res_y).

ans = calc(resx, resy);
cout << ans << "\n";