Программа курса:
Разбор задачи: Шахматный конь
Предложенный нами код:
def knightDialer(n: int) -> int:
MOD = 10**9 + 7
# Маппинг возможных ходов для каждой цифры
moves = {
0: [4, 6],
1: [8, 6],
2: [7, 9],
3: [4, 8],
4: [3, 9, 0],
5: [],
6: [1, 7, 0],
7: [2, 6],
8: [1, 3],
9: [2, 4]
}
# dp[i] хранит количество возможных номеров длины n, заканчивающихся на цифре i
dp = [1] * 10 # Для n=1, каждая цифра может быть начальной (один раз)
# Для длин более 1
for _ in range(n - 1):
new_dp = [0] * 10 # Новый список для хранения количества номеров на следующем шаге
for digit in range(10):
for next_digit in moves[digit]:
new_dp[next_digit] = (new_dp[next_digit] + dp[digit]) % MOD
dp = new_dp # Обновляем dp на новый шаг
return sum(dp) % MOD
Давайте подробно разберем решение задачи по вычислению количества возможных номеров, которые можно набрать на телефонной панели с использованием коня из шахмат. Важным моментом является, что конь может двигаться по определенным правилам, которые мы должны учесть при решении задачи.
Входные данные:
У нас есть два входных параметра:
n— длина номера телефона, который мы должны сформировать.- На вход также предполагается, что у нас есть шахматная доска в виде телефонной панели с цифрами от 0 до 9, где конь может начинать свое движение с любой из этих цифр и делать допустимые ходы.
Структура решения:
Модификатор
MOD: Для предотвращения переполнения при подсчете всех возможных комбинаций, мы будем брать результат по модулю 109+710^9 + 7, как это часто делается в задачах с большими числами.MOD = 10**9 + 7Словарь
moves: Этот словарь определяет, куда может переместиться конь с каждой цифры. Например, если конь стоит на цифре0, то он может прыгнуть на4или6. Важно, что для каждой цифры указаны только те клетки, куда конь может переместиться по правилам шахмат.moves = { 0: [4, 6], 1: [8, 6], 2: [7, 9], 3: [4, 8], 4: [3, 9, 0], 5: [], 6: [1, 7, 0], 7: [2, 6], 8: [1, 3], 9: [2, 4] }Здесь каждая цифра (от 0 до 9) отображается на список цифр, куда конь может перейти.
Инициализация списка
dp: Сначала создается списокdp, в котором для каждого индекса (цифры) хранится количество способов, которыми мы можем завершить номер, заканчивающийся на этой цифре. Для номера длины 1 количество таких способов для каждой цифры будет равно 1, потому что мы можем начать номер с любой цифры.dp = [1] * 10 # Для n=1, каждая цифра может быть начальной (один раз)Цикл по числам от 1 до
n-1: Дальше мы начинаем вычисления для номеров длины более 1. Каждый шаг в цикле представляет собой увеличение длины номера на 1. На каждом шаге мы обновляем количество возможных номеров для каждой цифры на основе предыдущего состояния.Мы создаем новый список
new_dp, в который будем записывать количество способов для каждой цифры на текущем шаге. Для каждой цифрыdigitпроверяем, куда можно прыгнуть, и для каждого возможного следующего шага добавляем к соответствующему элементу вnew_dp.for _ in range(n - 1): new_dp = [0] * 10 # Новый список для хранения количества номеров на следующем шаге for digit in range(10): for next_digit in moves[digit]: new_dp[next_digit] = (new_dp[next_digit] + dp[digit]) % MOD dp = new_dp # Обновляем dp на новый шагВ этой части решения:
- Мы обновляем список
dpпосле каждого шага, который увеличивает длину номера. - Используем информацию из словаря
moves, чтобы для каждой цифры найти все возможные переходы. - Важно отметить, что в процессе подсчета мы всегда берем результат по модулю 109+710^9 + 7, чтобы избежать переполнения.
- Мы обновляем список
Возврат результата: После того как мы посчитаем все возможные номера для длины
n, нам нужно просто вернуть сумму всех значений вdp, которая будет представлять количество всех возможных номеров длиныn, состоящих из допустимых переходов.return sum(dp) % MODВ этой строке мы подытоживаем количество всех возможных номеров, заканчивающихся на любой цифре, и возвращаем результат по модулю 109+710^9 + 7.
Пример:
Предположим, что n = 2. На первом шаге мы инициализируем dp, где все элементы равны 1. В следующем шаге мы обновим dp для номеров длины 2, учитывая возможные переходы по полям на шахматной доске. Мы будем поочередно проходить все цифры и для каждой цифры прибавлять количество переходов, которые возможны согласно словарю moves.