Разбор задачи: Шахматный конь

Предложенный нами код:

 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

Давайте подробно разберем решение задачи по вычислению количества возможных номеров, которые можно набрать на телефонной панели с использованием коня из шахмат. Важным моментом является, что конь может двигаться по определенным правилам, которые мы должны учесть при решении задачи.

Входные данные:

У нас есть два входных параметра:

  1. n — длина номера телефона, который мы должны сформировать.
  2. На вход также предполагается, что у нас есть шахматная доска в виде телефонной панели с цифрами от 0 до 9, где конь может начинать свое движение с любой из этих цифр и делать допустимые ходы.

Структура решения:

  1. Модификатор MOD: Для предотвращения переполнения при подсчете всех возможных комбинаций, мы будем брать результат по модулю 109+710^9 + 7, как это часто делается в задачах с большими числами.

    MOD = 10**9 + 7
    
  2. Словарь 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) отображается на список цифр, куда конь может перейти.

  3. Инициализация списка dp: Сначала создается список dp, в котором для каждого индекса (цифры) хранится количество способов, которыми мы можем завершить номер, заканчивающийся на этой цифре. Для номера длины 1 количество таких способов для каждой цифры будет равно 1, потому что мы можем начать номер с любой цифры.

    dp = [1] * 10  # Для n=1, каждая цифра может быть начальной (один раз)
    
  4. Цикл по числам от 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, чтобы избежать переполнения.
  5. Возврат результата: После того как мы посчитаем все возможные номера для длины n, нам нужно просто вернуть сумму всех значений в dp, которая будет представлять количество всех возможных номеров длины n, состоящих из допустимых переходов.

    return sum(dp) % MOD
    

    В этой строке мы подытоживаем количество всех возможных номеров, заканчивающихся на любой цифре, и возвращаем результат по модулю 109+710^9 + 7.


Пример:

Предположим, что n = 2. На первом шаге мы инициализируем dp, где все элементы равны 1. В следующем шаге мы обновим dp для номеров длины 2, учитывая возможные переходы по полям на шахматной доске. Мы будем поочередно проходить все цифры и для каждой цифры прибавлять количество переходов, которые возможны согласно словарю moves.

 



Вы должны Войти или Зарегистрироваться чтобы оставлять комментарии