Задание №21 ЕГЭ по информатике: разбор, шаблоны кода Python и анти-примеры | СмартКИМ
СмартКИМ УДОБНАЯ ПОДГОТОВКА К ЕГЭ И ОГЭ
Задачи №21 Решать в тренажере Войти в СмартКИМ
ЕГЭ (1–27) ОГЭ (1–15) Python: шпаргалка
Быстрый переход по номерам и темам
Повышенный / Высокий (3 балла) Время: 5-8 мин Python Рекурсивный шаблон games(s, m) Все задачи №{ topic_num } в каталоге

Задания №19, 20, 21. Теория игр (Одна и две кучи камней)

Тема: Выигрышные и проигрышные позиции, рекурсивная функция moves() и игра в 1-2 хода
Универсальный рекурсивный шаблон для решения всех трех заданий по теории игр (19, 20, 21) на две кучи камней за 3 минуты.

1. Универсальный шаблон теории игр на Python:

Определяем функцию game(h1, h2, moves_left), возвращающую True, если текущий игрок гарантированно выигрывает за заданное число полуходов:

  • Если сумма камней $\ge WIN$: проверяем, moves_left == 0 (победа на нужном ходу).
  • Если ходы кончились (moves_left == 0): поражение (False).
  • На своём ходу: игрок ищет ХОТЯ БЫ ОДИН выигрышный ход (any(...)).
  • На ходе противника: победа должна быть при ЛЮБОМ ответе противника (all(...)).

Разновидности и прототипы задания на экзамене

№19: Ваня выиграл 1-м ходом после неудачного хода Пети
Поиск минимального S.
№20: Петя выиграл 2-м ходом при любой игре Вани
Поиск двух значений S.
№21: Ваня выиграл 1-м или 2-м ходом при любой игре Пети
Поиск минимального S.

Боевой шаблон решения на Python

Запустить код в онлайн-песочнице
# === Универсальный шаблон Заданий 19, 20, 21 на Python ===

def moves(h):
    a, b = h
    return [(a + 1, b), (a * 2, b), (a, b + 1), (a, b * 2)]

# Рекурсивная функция: возвращает True, если игрок побеждает за k ходов
def game(h, k):
    if sum(h) >= 77:
        return k % 2 == 0
    if k == 0:
        return False
        
    next_moves = [game(m, k - 1) for m in moves(h)]
    
    # Если ход текущего игрока — достаточно ХОТЯ БЫ ОДНОГО выигрышного хода (any):
    # Если ход соперника — победа должна быть при ЛЮБОМ его ходе (all):
    if (k - 1) % 2 == 0:
        return any(next_moves)
    else:
        return all(next_moves)

print("--- Задание 19 (Ваня выигрывает 1-м ходом, k=2) ---")
# В 19 задаче часто условие: Петя ошибся (any вместо all на 1-м ходу):
for s in range(1, 70):
    if any(sum(m) >= 77 for m in moves((7, s))):
        pass # Петя мог выиграть сразу
    elif any(any(sum(m2) >= 77 for m2 in moves(m1)) for m1 in moves((7, s))):
        print("19:", s)
        break

print("--- Задание 20 (Петя выигрывает 2-м ходом, k=3) ---")
for s in range(1, 70):
    if not game((7, s), 1) and game((7, s), 3):
        print("20:", s)

print("--- Задание 21 (Ваня выигрывает 1-м или 2-м ходом, k=4) ---")
for s in range(1, 70):
    if not game((7, s), 2) and game((7, s), 4):
        print("21:", s)

Анти-примеры (Типичные ошибки vs Как делать правильно)

Как делать НЕ надо:
❌ Ошибка в Задании 20: Забыть условие 'not game(h, 1)'
Петя должен выигрывать строго вторым ходом, а не первым!
Как делать ПРАВИЛЬНО:
Правильно: Всегда проверять: not game(h, 1) and game(h, 3)
ГРОБ

ГРОБ №19-21: Игра на 3 кучи камней или с уменьшением камней

В игре 3 кучи камней `(a, b, c)`.

Как обойти ловушку: Просто добавьте третью переменную в кортеж `moves(h)` — логика функции `game` не изменится ни на символ!

Лайфхаки и подводные камни на экзамене:

  • Этот один рекурсивный скрипт решает сразу 3 первичных балла на экзамене за 3 минуты!
Банк реальных задач №21 Открыть в тренажере СмартКИМ