Фермеру Джону сообщили о местонахождении сбежавшей
коровы, и он хочет немедленно ее поймать. Он начинает с точки n на
числовой прямой, а корова находится в точке k на той же
числовой прямой. У фермера Джона есть два способа передвижения: ходьба и
телепортация.
·
Ходьба: ФД может
переместиться из любой точки x в точку x − 1 или x + 1 за одну минуту;
·
Телепортация: ФД
может переместиться из любой точки x в точку 2 * x за
одну минуту.
Если корова, не подозревая о преследовании, вообще не
двигается, сколько времени понадобится фермеру Джону, чтобы ее поймать?
Вход. Одна строка
содержит два целых числа n (0 ≤ n ≤ 105) и k
(0 ≤ k ≤ 105).
Выход. Выведите
наименьшее количество минут, за которое фермер Джон поймает сбежавшую корову.
Пример входа |
Пример выхода |
5 17 |
4 |
поиск в ширину
Абсциссы
на координатной прямой можно рассматривать как вершины графа, а способы
передвижения – как рёбра этого графа. Например, шаг вправо задаёт ребро между
вершинами x и x + 1, а телепортация – ребро между x и 2 * x.
Минимальное
количество минут, за которое фермер Джон сможет поймать сбежавшую корову,
соответствует длине кратчайшего пути между вершинами n и k. Для
его нахождения воспользуемся поиском в ширину, начиная с вершины n. Ответом
является кратчайшее расстояние до вершины k.
Пример
Рассмотрим самый быстрый маршрут, по которому фермер
Джон может добраться до коровы: 5 → 10 → 9 → 18 → 17.
Это занимает 4 минуты.
Рассмотрим пошаговое заполнение массива кратчайших расстояний
dist.
Реализация алгоритма
Объявим массив кратчайших расстояний dist и очередь q для выполнения
поиска в ширину.
#define MAX 200001
int dist[MAX];
queue<int> q;
Функция go отвечает за переход из вершины v в вершину to. Если dist[to]
≠ -1, то вершина to уже была
посещена ранее, и повторно в неё заходить не нужно.
void go(int v, int to)
{
if (dist[to] != -1) return;
Если вершина to ещё не посещалась, добавляем её
в очередь q и обновляем значение dist[to], прибавив единицу к
расстоянию от вершины v.
q.push(to);
dist[to] = dist[v] + 1;
}
Функция bfs реализует
поиск в ширину, начиная с вершины start.
void bfs(int start)
{
Инициализацируем данные, необходимые для поиска в
ширину.
memset(dist, -1, sizeof(dist));
dist[start] = 0;
q.push(start);
Начинаем основной цикл, который продолжается до тех
пор, пока очередь не станет пустой.
while (!q.empty())
{
Извлекаем вершину x из начала очереди.
int x = q.front(); q.pop();
Если достигнута позиция k, где находится корова,
завершаем поиск.
if (x == k) return;
Рассматриваем все
возможные способы передвижения – вправо, влево и телепортацию. Если переход
возможен, обновляем соответствующие массивы.
if (x + 1 < MAX) go(x, x + 1);
if (x - 1 >= 0) go(x, x
- 1);
if (2 * x < MAX) go(x, 2 * x);
}
}
Основная часть
программы. Читаем входные данные. Запускаем поиск в ширину из позиции n. Выводим ответ – минимальное количество минут, за
которое фермер Джон сможет добраться до позиции k.
scanf("%d %d", &n, &k);
bfs(n);
printf("%d\n", dist[k]);