21. Выигрышная стратегия: часть 3: #295303
Два игрока, Петя и Ваня, играют в следующую игру. Перед игроками лежат две кучи камней. Игроки ходят по очереди, первый ход делает Петя.
Известно, что Ваня выиграл своим первым ходом после неудачного хода Пети.
Для игры, описанной в задании $19$, найдите наименьшее значение $S$, при котором одновременно выполняются два условия:
- у Вани есть выигрышная стратегия, позволяющая ему выиграть первым или вторым ходом при любой игре Пети;
- у Вани нет стратегии, которая позволит ему гарантированно выиграть первым ходом.
Если найдено несколько значений $S$, в ответе запишите наименьшее из них.
Первый способ – математическое решение
Минимальное подходящее значение: $S=51$.
После первого хода Пети возможны позиции: $(12;51),\ (9;54),\ (18;51),\ (9;102)$.
Из позиции $(9;102)$ Ваня выигрывает сразу.
Если Петя получил $(12;51)$, Ваня удваивает первую кучу: $(12;51)\rightarrow(24;51)$.
После этого Петя может получить: $(27;51),\ (24;54),\ (48;51),\ (24;102)$, и из каждой позиции Ваня выигрывает следующим ходом.
Если Петя получил $(9;54)$, Ваня получает: $(9;54)\rightarrow(18;54)$.
Если Петя получил $(18;51)$, Ваня также получает: $(18;51)\rightarrow(18;54)$.
Из позиции $(18;54)$ Ваня гарантированно выигрывает своим вторым ходом.
При этом после хода Пети $(9;51)\rightarrow(12;51)$ Ваня не может выиграть сразу, поэтому гарантированной победы первым ходом у него нет.
Второй способ – решение с помощью Python
def moves(a, b):
return [(a + 3, b), (a, b + 3),
(a * 2, b), (a, b * 2)]
def win1(a, b):
return a + b < 129 and any(
x + y >= 129 for x, y in moves(a, b)
)
def win2(a, b):
if win1(a, b):
return True
return any(
all(
x + y < 129 and win1(x, y)
for x, y in moves(c, d)
)
for c, d in moves(a, b)
if c + d < 129
)
for S in range(1, 120):
petya = moves(9, S)
if (
all(a + b < 129 and win2(a, b) for a, b in petya)
and not all(win1(a, b) for a, b in petya)
):
print(S)
break
Программа проверяет, что после любого хода Пети Ваня может выиграть первым или вторым ходом, но не может гарантированно выиграть своим первым ходом.
Программа выведет: $51$.