Тема 23. Оператор присваивания и ветвления

23.08 Прочие прототипы

Вспоминай формулы по каждой теме
Решай новые задачи каждый день
Вдумчиво разбирай решения
ШКОЛКОВО.
Готовиться с нами - ЛЕГКО!
Подтемы раздела оператор присваивания и ветвления
Решаем задачу:

Ошибка.
Попробуйте повторить позже

Задача 1#30491

Исполнитель Щелчок очень хочет быть похожим на исполнителя Робота, поэтому учится двигаться по прямоугольной системе координат. У исполнителя есть три команды:

1. Прибавить 2 к координате X ((1, 2) → (3, 2))

2. Умножить координату X на 2 ((1, 2) → (2, 2))

3. Переместиться вверх на любое количество клеток от 1 до разницы между нынешней координатой и стеной, (стеной считается прямая y = «значение Y у конечной точки»)

Пример для команды 3, y = 5 — стена, ((1, 1) → (1, 2), или (1, 1) → (1, 3), или ..., или (1, 1) → (1, 5))

Программа для исполнителя — это последовательность команд.

Сколько существует различных программ, которые приведут исполнителя из точки с координатами (1, 2) в точку с координатами (12, 19).

Показать ответ и решение

Решение рекурсией

Мы используем рекурсивную функцию f(st,f n)  , которая считает количество программ, переводящих текущую координату st = (x,y)  в конечную fn = (x ,y )
       f  f  . Идея такова:

1. Если текущие координаты совпадают с конечными (st == fn)  , то найден один путь, возвращаем 1. 2. Если текущие координаты превышают конечные по X  или Y  (st[0] > fn [0] или st[1] > fn[1])  , путь невозможен, возвращаем 0. 3. В остальных случаях мы рассматриваем все возможные действия: - Увеличиваем X  на 2 и рекурсивно считаем пути из (st[0]+ 2,st[1])  - Умножаем X  на 2 и рекурсивно считаем пути из (st[0]∗2,st[1])  - Двигаемся вверх на все возможные значения от 1 до (f n[1]− st[1])  и суммируем пути из (st[0],st[1]+ i)  для каждого i

Мы используем lru_cache для мемоизации, чтобы повторные вызовы с одинаковыми координатами не вычислялись заново. Рекурсивный вызов f((1,2),(12,19)) вернет общее количество программ.

# Импортируем декоратор для кеширования результатов рекурсии
from functools import lru_cache

# Определяем рекурсивную функцию f(st, fn), где st - текущие координаты, fn - конечные
@lru_cache(None)
def f(st, fn):
    # Если достигли конечной точки, возвращаем 1
    if st == fn:
        return 1
    # Если текущие координаты вышли за пределы конечных, возвращаем 0
    if st[0] > fn[0] or st[1] > fn[1]:
        return 0
    # Считаем количество программ при увеличении X на 2
    c1 = f((st[0] + 2, st[1]), fn)
    # Считаем количество программ при умножении X на 2
    c2 = f((st[0] * 2, st[1]), fn)
    # Создаем список для подсчета вариантов движения вверх
    c = [0] * (fn[1] - st[1] + 1)
    # Перебираем все возможные вертикальные перемещения вверх
    for i in range(1, fn[1] - st[1] + 1):
        c[i] = f((st[0], st[1] + i), fn)
    # Суммируем все возможные варианты
    return c1 + c2 + sum(c)

# Вычисляем и выводим количество программ от (1,2) до (12,19)
print(f((1, 2), (12, 19)))

Решение динамикой

Мы создаем двумерный массив dp[x][y]  , где x  и y  — координаты, а dp[x][y]  — количество программ, ведущих из начальной точки в (x,y)  .

1. Инициализируем массив нулями и присваиваем dp[1][2] = 1  , так как стартуем из точки (1,2) одним способом. 2. Проходим по всем координатам x  от 1 до 12 и y  от 2 до 19: - Если x + 2 ≤ 12  , добавляем dp[x][y]  к dp[x + 2][y]  - Если 2 ∗x ≤ 12  , добавляем dp[x][y]  к dp[2∗ x][y]  - Для вертикального движения перебираем все координаты to  от y+ 1  до 19 и добавляем dp[x][y]  к dp[x ][to]

3. После завершения всех итераций dp[12][19]  хранит количество программ, ведущих в конечную точку.

# Создаем двумерный массив для координат от 0 до 12 по X и от 0 до 19 по Y
dp = [[0] * 20 for i in range(13)]
# Инициализация стартовой точки
dp[1][2] = 1
# Перебираем все координаты X
for x in range(1, 13):
    # Перебираем все координаты Y
    for y in range(2, 20):
        # Если можно увеличить X на 2, добавляем количество программ
        if x + 2 < 13:
            dp[x + 2][y] += dp[x][y]
        # Если можно умножить X на 2, добавляем количество программ
        if x * 2 < 13:
            dp[x * 2][y] += dp[x][y]
        # Перебираем вертикальные перемещения вверх
        for to in range(y + 1, 20):
            dp[x][to] += dp[x][y]

# Выводим количество программ, ведущих из (1,2) в (12,19)
print(dp[12][19])

Ответ: 1629356032

Специальные программы

Все специальные программы

Программа
лояльности v2.0

Приглашай друзей в Школково и получай вознаграждение до 10%!

Крути рулетку
и выигрывай призы!

Крути рулетку и покупай курсы со скидкой, которая привязывается к вашему аккаунту.

Бесплатное онлайн-обучение

Для школьников из приграничных территорий России, проживающих в ДНР, ЛНР, Херсонской, Запорожской, Белгородской, Курской, Брянской областях и Крыму.

Налоговые вычеты

Узнай, как получить налоговый вычет при оплате обучения в «Школково».

Специальное предложение
для учителей

Бесплатный доступ к любому курсу подготовки к ЕГЭ, ОГЭ и олимпиадам от «Школково». Мы с вами делаем общее и важное дело, а потому для нас очень значимо быть чем-то полезными для учителей по всей России!

Вернём деньги за курс
за твою сотку на ЕГЭ

Сдать экзамен на сотку и получить обратно деньги за подготовку теперь вполне реально!

cyberpunkMouse
cyberpunkMouse
Рулетка
Вы можете получить скидку в рулетке!