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

23.06 Количество программ из A в B где траектория вычислений N команда

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

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

Задача 1#58503

Исполнитель Повторюша преобразует число, записанное на экране. У исполнителя есть шесть команд, которым присвоены номера:

1. Прибавить 1.

2. Прибавить 2.

3. Прибавить 3.

4. Умножить на 2.

5. Умножить на 3.

6. Умножить на 4.

Программа для исполнителя Повторюша – это последовательность команд. Сколько различных результатов можно получить из исходного числа 1 после выполнения программы, содержащей 10 команд, если известно, то можно использовать только те команды, номера которых отличаются на 1 от номера команды, сделанной на предыдущем шаге (на первом шаге можно использовать любую команду)?

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

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

Мы используем рекурсию для перебора всех возможных последовательностей команд, соблюдая условие о допустимых номерах команд на каждом шаге. Определим функцию f(a, h, c), где:

- a  — текущее значение на экране;

- h  — количество выполненных команд;

- c  — номер последней команды, которая была выполнена (0 для первого шага, когда предыдущей команды нет).

1. На каждом шаге мы проверяем, достигли ли количества команд, равного 10:

- если да, добавляем текущее значение a  в множество s, чтобы фиксировать уникальные результаты, и завершаем текущий путь рекурсии;

2. Если это первый шаг (c = 0  ), разрешены все команды, поэтому вызываем функцию рекурсивно для всех шести команд: прибавление 1, 2, 3 и умножение на 2, 3, 4;

3. Если это не первый шаг, проверяем номер последней команды и разрешаем только команды с номерами, отличающимися на 1:

- Например, если c = 2  , то на следующем шаге разрешены команды 1 и 3, так как их номера отличаются на 1 от 2;

- Для c = 1  разрешена только команда 2;

- Для c = 6  разрешена только команда 5;

- Для промежуточных номеров выполняем оба варианта (влево и вправо), чтобы соблюсти условие различия номеров на 1.

На каждом рекурсивном вызове мы увеличиваем счётчик шагов h  на 1 и передаём новый номер выполненной команды, чтобы следующий вызов функции мог правильно определить доступные команды. Когда рекурсия достигает 10 шагов, значение добавляется в множество s. После завершения всех рекурсивных веток количество уникальных значений в s даёт ответ на задачу.

# Создаем множество для хранения всех уникальных результатов
s = set()

# Определяем рекурсивную функцию
def f(a, h, c):
    # Если выполнено 10 команд, добавляем результат в множество
    if h == 10:
        s.add(a)
        return
    # Если это первый шаг, можно использовать любую команду
    if c == 0:
        f(a + 1, h + 1, 1)   # прибавляем 1
        f(a + 2, h + 1, 2)   # прибавляем 2
        f(a + 3, h + 1, 3)   # прибавляем 3
        f(a * 2, h + 1, 4)   # умножаем на 2
        f(a * 3, h + 1, 5)   # умножаем на 3
        f(a * 4, h + 1, 6)   # умножаем на 4
    # Если последняя команда была 1, следующий шаг только команда 2
    elif c == 1:
        f(a + 2, h + 1, 2)
    # Если последняя команда была 2, следующий шаг команды 1 и 3
    elif c == 2:
        f(a + 1, h + 1, 1)
        f(a + 3, h + 1, 3)
    # Если последняя команда была 3, следующий шаг команды 2 и 4
    elif c == 3:
        f(a + 2, h + 1, 2)
        f(a * 2, h + 1, 4)
    # Если последняя команда была 4, следующий шаг команды 3 и 5
    elif c == 4:
        f(a + 3, h + 1, 3)
        f(a * 3, h + 1, 5)
    # Если последняя команда была 5, следующий шаг команды 4 и 6
    elif c == 5:
        f(a * 2, h + 1, 4)
        f(a * 4, h + 1, 6)
    # Если последняя команда была 6, следующий шаг только команда 5
    elif c == 6:
                                                                                                     
                                                                                                     
        f(a * 3, h + 1, 5)

# Запускаем рекурсию с начальным числом 1, нулевым количеством шагов и отсутствием предыдущей команды
f(1, 0, 0)

# Выводим количество уникальных результатов
print(len(s))

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

В динамическом подходе мы моделируем все возможные состояния после каждого шага программы с помощью списка a, где каждый элемент — это пара [значение, номер последней команды].

1. Изначально в списке только одно состояние: [1, ’0’] — число 1 и отсутствие предыдущей команды.

2. Для каждого из 10 шагов:

- Создаём новый список состояний после выполнения текущего шага.

- Для каждого состояния определяем список всех возможных команд: прибавление 1,2,3 и умножение на 2,3,4.

- Если предыдущая команда ’0’ (первый шаг), добавляем все команды в новый список.

- Если предыдущая команда крайняя (1 или 6), добавляем только соседнюю команду, чтобы не выйти за границы.

- Для остальных случаев добавляем две соседние команды: c-1 и c+1.

3. После 10 шагов остаётся множество всех возможных конечных значений. Преобразуем его в множество, чтобы исключить повторения, и считаем длину множества — это и есть количество различных результатов.

# Начальное состояние: число 1, предыдущая команда отсутствует
a = [[1, ’0’]]

# Выполняем 10 шагов программы
for i in range(10):
    n = len(a)
    for j in range(n):
        l = a.pop(0)
        # Список всех возможных команд
        command = [[l[0] + 1, ’1’], [l[0] + 2, ’2’], [l[0] + 3, ’3’],
                   [l[0] * 2, ’4’], [l[0] * 3, ’5’], [l[0] * 4, ’6’]]
        # Первый шаг - все команды доступны
        if l[1] == ’0’:
            for k in range(6):
                a.append(command[k])
        # Крайние команды: только одна соседняя
        elif l[1] == ’1’:
            a.append(command[1])
        elif l[1] == ’6’:
            a.append(command[4])
        # Для остальных команд: добавляем соседние по номерам
        else:
            a.append(command[int(l[1]) - 2])
            a.append(command[int(l[1])])

# Преобразуем все значения в множество, чтобы исключить дубликаты
a = set([j[0] for j in a])

# Выводим количество уникальных результатов
print(len(a))

Ответ: 445

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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