Абсциси на координатній прямій можна розглядати як вершини графа, а способи пересування — як ребра цього графа. Наприклад, крок праворуч задає ребро між вершинами та x + 1, а телепортація — ребро між та 2 * x.
Мінімальна кількість хвилин, за яку фермер Джон зможе зловити втіклу корову, відповідає довжині найкоротшого шляху між вершинами та . Для його знаходження скористаємося пошуком у ширину, починаючи з вершини . Відповіддю є найкоротша відстань до вершини .
Приклад
Розгляньмо найшвидший маршрут, яким фермер Джон може дістатися до корови: 5 → 10 → 9 → 18 → 17. Це займає хвилини.
Розгляньмо покрокове заповнення масиву найкоротших відстаней .
Реалізація алгоритму
Оголосимо масив найкоротших відстаней та чергу для виконання пошуку у ширину.
#define MAX 200001
int dist[MAX];
queue<int> q;Функція go відповідає за перехід з вершини в вершину . Якщо dist[to] \ne -1, то вершина уже була відвідана раніше, і повторно в неї заходити не потрібно.
void go(int v, int to)
{
if (dist[to] != -1) return;Якщо вершина ще не відвідувалась, додаємо її в чергу і оновлюємо значення dist[to], додавши одиницю до відстані від вершини .
q.push(to);
dist[to] = dist[v] + 1;
}Функція bfs реалізує пошук у ширину, починаючи з вершини .
void bfs(int start)
{Ініціалізуємо дані, необхідні для пошуку у ширину.
memset(dist, -1, sizeof(dist));
dist[start] = 0;
q.push(start);Починаємо основний цикл, який триває доти, доки черга не стане пустою.
while (!q.empty())
{Витягуємо вершину з початку черги.
int x = q.front(); q.pop();Якщо досягнуто позицію , де знаходиться корова, завершуємо пошук.
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);
}
}Основна частина програми. Читаємо вхідні дані. Запускаємо пошук у ширину з позиції . Виводимо відповідь — мінімальну кількість хвилин, за яку фермер Джон зможе дістатися до позиції .
scanf("%d %d", &n, &k);
bfs(n);
printf("%d\n", dist[k]);