В теории графов , дерево – это неориентированный граф , в котором любые две вершины соединены ровно одним путем.
Корнем будет являться исходное число, а листами – число, в которое надо прийти.
![Задание 23. Решение деревом [theory], изображение №1](https://sun9-33.userapi.com/impf/45OzljgKNZ9BBJzqBVicF3yJe-PyWuX9skIKoQ/QLA8g2WxcTA.jpg?size=619x566&quality=96&sign=43682020b1b90ef0fd5e8f690366d8c1&type=album)
Типовое задание:
У исполнителя есть команды:
- Увеличить число
2. Увеличить число
Сколько существует программ, для которых при исходом числе a результатом является число b
Если строить полное дерево, оно получится очень большим. Рекомендуется применять методы динамического программирования: не считать вершины, которые уже были подсчитаны ранее.
Дополнительные ограничения мы применяем так:
- Траектория вычислений содержит число n.
Разбиваем дерево решений на два дерева. Сначала находим количество программ из a в n, потом из n в a. Полученные числа перемножаем. - Траектория вычислений не содержит числа k.
В дереве не учитываем ветки, где ход идет в число k.
Рассмотрим примеры.
У исполнителя Утроитель две команды, которым присвоены номера:
1. прибавь 1
2. умножь на 3
Сколько есть программ, которые число 1 преобразуют в число 20?
У данного исполнителя две команды. Вторая более “весомая” чем первая, т.е. делает более “сильный” ход – больше увеличивает число. Поэтому будем отталкиваться от первой команды.
Само решение будет идти в два хода: сначала мы спускаемся вниз, до конечного числа. Затем обратный ход – поднимаемся до исходного числа с подсчетом количества программ.
Поскольку получить 20 из 1 прибавлением 1 можно за 19 команд, строить такое большое дерево не рационально. Из числа 7 мы уже не сможем получить 20 с помощью второй команды, мы его перепрыгнем. Значит, из 7 есть только один способ уйти в 20 — это прибавлять 1.
![Задание 23. Решение деревом [theory], изображение №2](https://sun9-19.userapi.com/impf/gCXBwSyCTTerVjfh_vCs4VCuuwfPOky6HQmlNQ/jzH5OAPWicU.jpg?size=541x579&quality=96&sign=4d9f6ff7879650be9a52b195aa9ff526&type=album)
В дереве нижним индексом приписано количество способов получить число 20. Из всех чисел из диапазона 7..20 есть ровно один такой способ.
Из 6 мы можем попасть с помощью второй команды в число 18, которое как раз находится в этом диапазоне. Для подсчета количества программ для числа 6 мы будем складывать количество программ в числах, в которые можно попасть из 6
![Задание 23. Решение деревом [theory], изображение №3](https://sun9-4.userapi.com/impf/6LVH7-lXT-T5WJdqTUVFMAU3MIhtQ1m5F9oD9w/sxUlfXXHLbQ.jpg?size=541x579&quality=96&sign=0314346d2aaf0181b574498c01345d27&type=album)
Продолжим подниматься вверх. Теперь мы будем опираться на уже подсчитанные значения. Такие числа выделены синим
![Задание 23. Решение деревом [theory], изображение №4](https://sun9-26.userapi.com/impf/MpGvZ0ILooiksmwdzCrGmxtmhqtVsof3rGOUmA/X3thh0prdTE.jpg?size=617x579&quality=96&sign=5f8429e0d4c8e87811537037b73ad31a&type=album)
Таким образом, получилось 12 программ.
Другой пример
Исполнитель Июнь15 преобразует число на экране. У исполнителя есть две команды, которым присвоены номера:
1. Прибавить 1
2. Умножить на 2
Первая команда увеличивает число на экране на 1, вторая умножает его на 2. Программа для исполнителя Июнь15 – это последовательность команд. Сколько существует программ, для которых при исходном числе 2 результатом является число 40 и при этом траектория вычислений содержит число 20 и не содержит число 8?
В данном задании присутствует сразу два ограничения.
Чтобы учесть, что траектория содержит число 20, мы разобьем решение на два этапа: сначала найдем количество программ из 2 в 20, затем из 20 в 40.
Второе ограничение – что нельзя в число 8 – проявит себя только в первой части решения.
При построении дерева по команде +1 мы упираемся в число 8, в которое попасть нельзя. При этом после него, т.е. из 9, мы можем все посчитать.
![Задание 23. Решение деревом [theory], изображение №5](https://sun9-61.userapi.com/impf/fsVw9ftx9QJ6F6TMnLdNaBpzrySy8N1GU5_PUQ/ZHSjJv16HPY.jpg?size=678x744&quality=96&sign=c2c22613dc1fd600a2c36f87e729d96c&type=album)
Все числа от 11 до 20 при умножении на 2 перепрыгивают 20, поэтому из каждого из них есть только один способ попасть в 20: это прибавлять 1.
Для числа 10 мы получаем 2 способа.
Продолжим обратный ход для чисел от 7 до 2
Для числа 7 мы получаем количество программ равное количеству программ для 14.
Второй раз нам 8 встречается при попытке умножить 4 на 2. Не забываем его проигнорировать.
![Задание 23. Решение деревом [theory], изображение №6](https://sun9-31.userapi.com/impf/uePSsbtvkq_4tQqWyyQdp5DS9-8Wjo9CugJBsw/dZVcz4sOhEo.jpg?size=737x744&quality=96&sign=a18b8b861c84f34d9f7d58955b0ac4dd&type=album)
В итоге, получилось 10 способов.
Теперь посчитаем способы из 20 в 40. На самом деле, их не очень много.
Итоговое количество способов это 10 * 2 = 20.
![Задание 23. Решение деревом [theory], изображение №7](https://sun9-49.userapi.com/impf/K-V-BGfpQUklYI0Dd0gIse4kih_BOdjFSHWfiA/wTrok_k8syQ.jpg?size=807x596&quality=96&sign=a8df91c52c625795161b7907244671ba&type=album)
Таким образом, с помощью дерева мы получаем решение, в котором можно учесть все ограничения и относительно компактную запись. Я предпочитаю именно этот способ ручного решения, вместо табличного.