Задача к ЕГЭ по информатике на тему «Теория игр» №2

Для игры, описанной ранее, найдите максимальное значение S, при котором одновременно выполняются два условия:

— у Вани есть выигрышная стратегия, позволяющая ему выиграть первым или вторым ходом при любой игре Пети;

— у Вани нет стратегии, которая позволит ему гарантированно выиграть первым ходом.

Решение руками

Из предыдущих заданий мы знаем, что в значениях [44;87] Петя побеждает своим первым ходом и в значениях (11,12,13,14,15,16,17,18,19,20,21,23,25,27,29,31,33,35,37,39,41)  Петя побеждает вторым ходом. Значение, из которого ВСЕ первые ходы ведут в вышеописанные значения – это значение, в котором Ваня гарантированно побеждает вторым ходом или первым при неудачной игре Пети. Распишем значения и стратегии, при которых Ваня побеждает вторым или первым ходом:

S = 6  . Петя может увеличить количество камней до 12  ходом ∗2  . Ваня выиграет вторым ходом.

S = 8  . Петя может увеличить количество камней до 16  ходом ∗2  . Ваня выиграет вторым ходом.

S = 10  . Петя может увеличить количество камней до 20  ходом ∗2  . Ваня выиграет вторым ходом.

В ответ нужно указать максимальное значение S. Ответ: 10

Решение БУ

from functools import lru_cache
@lru_cache(None)
def game(first_heap): # функция игры
    if first_heap >= 88: # если камней в куче стало больше 87
        return 0 # прекращаем игру
    moves = [] # cписок всех возможных ходов в партии
    if first_heap % 2 == 0: # если количество камней в куче является чётным
        # то можем сделать только ход *2, так как чётное*чётное = чётное
        moves = [game(first_heap*2)]
    else: # если количество камней в куче является нечётным
        # то можем сделать только любой ход, так как нечётное*чётное = чётное и нечётное + нечётное = чётное
        moves = [game(first_heap * 2),game(first_heap+1),game(first_heap+3)]
    petya_win = [i for i in moves if i <= 0]
    if petya_win: # проверяем есть ли выигрыш Пети в данной позиции
        return -max(petya_win) + 1
    else: # если в данной позиции выигрыш Вани
        return -max(moves)

for i in range(1,88):
    # если в данной позиции возможен выигрыш Вани вторым ходом
    if game(i) == -2:
        print(i)

Решение АР

from functools import lru_cache
def moves(h):
    a = [h * 2]
    if (h + 1) % 2 == 0:
        a += [h + 1]
        a += [h + 3]
    return a
@lru_cache(None)
def f(h):
    if h >= 88:
        return ’END’
    if any(f(x) == ’END’ for x in moves(h)):
        return ’P1’
    if all(f(x) == ’P1’ for x in moves(h)):
        return ’V1’
    if any(f(x) == ’V1’ for x in moves(h)):
        return ’P2’
    if all(f(x) == ’P1’ or f(x) == ’P2’ for x in moves(h)):
        return ’V2’
for s in reversed(range(1, 88)):
    if f(s) == ’V2’:
        print(s)
        break

 

Ответ: 10
Оцените статью
Я решу все!