Школа программиста

Забыли пароль?
[задачи] [курсы] [олимпиады] [регистрация]
Логин:   Пароль:    
Скрыть меню
О школе
Правила
Олимпиады
Фотоальбом
Гостевая
Форум
Архив олимпиад
Архив задач
Состояние системы
Рейтинг
Курсы
Новичкам
Работа в системе
Курсы ККДП
Дистрибутивы
Статьи
Ссылки


 

Алхимия

(Время: 1 сек. Память: 16 Мб Сложность: 42%)

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

Пожалуй, наибольшую сложность в задаче представляет процесс формализации данных от строковых наименований химических веществ к обычному числовому представлению. Для этого следует провести нумерацию описанных во входных данных веществ и далее обращаться к ним по номерам. Для этого определим некоторую функцию GetID(name), которая по названию вещества name будет возвращать его номер. Наименования веществ будем хранить в некотором массиве p, причем название вещества c номером k будет храниться в p[k]. Используем пееменную n для хранения общего количества веществ. Функция GetID будет не только возвращать номер вещества, но и добавлять его в массив p, если ранее такого вещества не было. Данную функцию можно описать следующим образом:

  int GetID(name){
    for i=0..n-1
      if(p[i]==s) return i
    p[n]=s
    return n++
  }

В процессе чтения данных определим матрицу смежности a[i][j], где в a[i][j] будет 1, если возможно из вещества с номером i получить вещество с номером j, в противном случае a[i][j] будет равно 0. Заметим, что процесс формирования данной матрицы возможно совместно с чтением данных и заполнением массива p. Сам весь этот процесс можно представить следующим алгоритмом:

  read(m)
  a={0,…,0}
  for i=1..m{
    read(src, s, dest)
    a[GetID(src)][GetID(dest)]=1
  }
  Read(src, dest)

После мы в переменных src и dest будем иметь названия исходного и получаемого веществ, а в массиве a – матрицу смежности. Применим волновой алгортим (поиск в ширину) для нахождения ответа на поставленную задачу. Используем некоторый массив d, где в d[k] будем хранить количество шагов, необходимых для получения вещества с номером k из исходного. Пока решение не найдено, будем там хранить нулевое значение. Для удобства будем хранить в d[k] значение, превышающее на единицу требуемое значение количества шагов. Так, первоначально обнулим массив, а d[start] положим равным 1 (здесь start=GetID(src)). Далее, присвоим всем d[j] значение 2, если a[start][j]=1. Это будет означать, что все такие вещества с номером j можно получить за одну реакцию. Далее всем d[j] присвоим 3, где для некоторого i a[i][j]=1 и d[i]=2. Так найдем все вершины, которые возможно достичь за 2 шага и т.д., на k-м шаге будем помечать вершины значением k+1, в которые можно достичь за k шагов. За n-1 таких действий мы заполним массив d, а ответом на задачу будет значение d[GetID(dest)]-1. Вышеописанный механизм заполнения массива d может быть представлен следующим образом:

  d[GetID(src)]=1
  for k=1..n-1
    for i=0..n-1
      if(d[i]==k)
        for j=0..n-1
           if(a[i][j]==1 and d[j]==0) d[j]=k+1

[Обсуждение] [Все попытки] [Задача]


Красноярский краевой Дворец пионеров, (c)2006 - 2026, ИНН 246305493507, E-mail: admin@acmp.ru