Bu inəyi tut#7748

Bu inəyi tut (Həll təhlili)

Koordinat düz xəttindəki absissaları qrafın zirvələri kimi, hərəkət üsullarını isə qrafın kənarları kimi nəzərdən keçirə bilərik. Məsələn, sağa addım atmaq və x + 1 zirvələri arasında bir kənar qurur, teleportasiya isə və 2 * x arasında bir kənar qurur.

Fermer Conun qaçmış inək tutması üçün lazım olan minimal dəqiqələr sayı və zirvələri arasında olan ən qısa yolun uzunluğuna uyğundur. Bu yolun tapılması üçün zirvə -dən başlayaraq genişlik üzrə axtarışdan istifadə edək. Cavab kimi zirvəsinə olan ən qısa məsafə veriləcək.

Nümunə

Fermer Conun inəyə çatmağın ən sürətli yolunu nəzərdən keçirək: 5 → 10 → 9 → 18 → 17. Bu dəqiqə çəkir.

Gəlin, qısa məsafə ilə massivinin ardıcıl doldurulmasına baxaq.

Alqoritmin təcrübi tətbiqi

Qısa məsafələrin massivini və genişlik üzrə axtarış üçün növbəni elan edək.

#define MAX 200001
int dist[MAX];
queue<int> q;

go funksiyası zirvəsindən zirvəsinə keçməyi təmin edir. Əgər dist[to] ≠ -1 olarsa, zirvəsi artıq ziyarət edilib və yenidən ora getməyə ehtiyac yoxdur.

void go(int v, int to)
{
  if (dist[to] != -1) return;

Əgər zirvəsi hələ ziyarət olunmayıbsa, onu növbəyə daxil edirik və dist[to] dəyərini zirvəsindən olan məsafəyə bir əlavə edərək yeniləyirik.

  q.push(to);
  dist[to] = dist[v] + 1;
}

bfs funksiyası zirvəsindən başlayaraq genişlik üzrə axtarışı həyata keçirir.

void bfs(int start)
{

Genişlik üzrə axtarış üçün zəruri olan məlumatları inicializasiya edirik.

  memset(dist, -1, sizeof(dist));
  dist[start] = 0;
  q.push(start);

Əsas dövrəyə başlayırıq, növbə boş olmadıqca davam edirik.

  while (!q.empty())
  {

Növbənin başlanğıcından zirvəsini çıxarırıq.

    int x = q.front(); q.pop();

Əgər inəyi tutmalı olan mövqeyinə çatılarsa, axtarışı dayandırırıq.

    if (x == k) return;

Bütün mümkün hərəkət üsullarını nəzərdən keçiririk — sağa, sola və teleportasiya. Əgər keçid mümkündürsə, uyğun massivləri yeniləyirik.

    if (x + 1 < MAX) go(x, x + 1);
    if (x - 1 >= 0) go(x, x - 1);
    if (2 * x < MAX) go(x, 2 * x);
  }
}

Proqramın əsas hissəsini. Giriş məlumatlarını oxuyuruq. mövqeyindən genişlik üzrə axtarışı başladırıq. Cavabı – fermer Conun mövqeyinə çatması üçün lazım olan minimal dəqiqələr sayını çap edirik.

scanf("%d %d", &n, &k);
bfs(n);
printf("%d\n", dist[k]);