🐍 25 Π°Π»Π³ΠΎΡ€ΠΈΡ‚ΠΌΠΎΠ² динамичСского программирования, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ Π΄ΠΎΠ»ΠΆΠ΅Π½ Π·Π½Π°Ρ‚ΡŒ ΠΊΠ°ΠΆΠ΄Ρ‹ΠΉ программист

Π’ этой ΡΡ‚Π°Ρ‚ΡŒΠ΅ ΠΌΡ‹ рассмотрим 25 основных Π°Π»Π³ΠΎΡ€ΠΈΡ‚ΠΌΠΎΠ² динамичСского программирования с Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΠ΅ΠΉ Π½Π° Python, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ Π΄ΠΎΠ»ΠΆΠ΅Π½ Π·Π½Π°Ρ‚ΡŒ ΠΊΠ°ΠΆΠ΄Ρ‹ΠΉ, ΠΊΡ‚ΠΎ увлСкаСтся спортивным ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ΠΌ.

Данная ΡΡ‚Π°Ρ‚ΡŒΡ являСтся ΠΏΠ΅Ρ€Π΅Π²ΠΎΠ΄ΠΎΠΌ. Автор: Rishita Shaw. Бсылка Π½Π° ΠΎΡ€ΠΈΠ³ΠΈΠ½Π°Π».

ДинамичСскоС ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ β€” популярный ΠΌΠ΅Ρ‚ΠΎΠ΄ Π² ΠΊΠΎΠΌΠΏΡŒΡŽΡ‚Π΅Ρ€Π½Ρ‹Ρ… Π½Π°ΡƒΠΊΠ°Ρ… ΠΈ Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚ΠΊΠ΅ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ½ΠΎΠ³ΠΎ обСспСчСния, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ ΠΈΠ³Ρ€Π°Π΅Ρ‚ Ρ€Π΅ΡˆΠ°ΡŽΡ‰ΡƒΡŽ Ρ€ΠΎΠ»ΡŒ Π² спортивном ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠΈ. Π­Ρ‚ΠΎ ΠΌΠ΅Ρ‚ΠΎΠ΄ Ρ€Π΅ΡˆΠ΅Π½ΠΈΡ слоТных ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌ ΠΏΡƒΡ‚Π΅ΠΌ ΠΈΡ… разбиСния Π½Π° Π±ΠΎΠ»Π΅Π΅ ΠΌΠ΅Π»ΠΊΠΈΠ΅ ΠΏΠΎΠ΄Π·Π°Π΄Π°Ρ‡ΠΈ ΠΈ Ρ€Π΅ΡˆΠ΅Π½ΠΈΡ ΠΊΠ°ΠΆΠ΄ΠΎΠΉ ΠΏΠΎΠ΄Π·Π°Π΄Π°Ρ‡ΠΈ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΎΠ΄ΠΈΠ½ Ρ€Π°Π· с сохранСниСм Ρ€Π΅ΡˆΠ΅Π½ΠΈΠΉ ΠΏΠΎΠ΄Π·Π°Π΄Π°Ρ‡, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΈΡ… ΠΌΠΎΠΆΠ½ΠΎ Π±Ρ‹Π»ΠΎ ΠΏΠΎΠ²Ρ‚ΠΎΡ€Π½ΠΎ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ ΠΏΡ€ΠΈ нСобходимости. Π’ этой ΡΡ‚Π°Ρ‚ΡŒΠ΅ ΠΌΡ‹ рассмотрим Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΡ‹Π΅ Π°Π»Π³ΠΎΡ€ΠΈΡ‚ΠΌΡ‹ динамичСского программирования, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ Π΄ΠΎΠ»ΠΆΠ΅Π½ Π·Π½Π°Ρ‚ΡŒ ΠΊΠ°ΠΆΠ΄Ρ‹ΠΉ, ΠΊΡ‚ΠΎ увлСкаСтся спортивным ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ΠΌ.

1. Числа Π€ΠΈΠ±ΠΎΠ½Π°Ρ‡Ρ‡ΠΈ

ΠŸΠΎΡΠ»Π΅Π΄ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΠ½ΠΎΡΡ‚ΡŒ Π€ΠΈΠ±ΠΎΠ½Π°Ρ‡Ρ‡ΠΈ β€” это Ρ…ΠΎΡ€ΠΎΡˆΠΎ извСстная ΠΏΠΎΡΠ»Π΅Π΄ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΠ½ΠΎΡΡ‚ΡŒ чисСл, опрСдСляСмая Ρ€Π΅ΠΊΡƒΡ€Ρ€Π΅Π½Ρ‚Π½Ρ‹ΠΌ ΡΠΎΠΎΡ‚Π½ΠΎΡˆΠ΅Π½ΠΈΠ΅ΠΌ F(n) = F(n-1) + F(n-2), Π³Π΄Π΅ F(0) = 0 ΠΈ F(1) = 1. ΠŸΡ€ΠΎΡΡ‚Ρ‹ΠΌ рСкурсивным Π°Π»Π³ΠΎΡ€ΠΈΡ‚ΠΌΠΎΠΌ вычислСния чисСл Π€ΠΈΠ±ΠΎΠ½Π°Ρ‡Ρ‡ΠΈ Π±Ρ‹Π»ΠΎ Π±Ρ‹ прямоС использованиС Ρ€Π΅ΠΊΡƒΡ€Ρ€Π΅Π½Ρ‚Π½ΠΎΠ³ΠΎ ΡΠΎΠΎΡ‚Π½ΠΎΡˆΠ΅Π½ΠΈΡ, Π½ΠΎ это ΠΏΡ€ΠΈΠ²Π΅Π»ΠΎ Π±Ρ‹ ΠΊ ΡΠΊΡΠΏΠΎΠ½Π΅Π½Ρ†ΠΈΠ°Π»ΡŒΠ½ΠΎΠΉ Π²Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎΠΉ слоТности. ДинамичСскоС ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ позволяСт Ρ€Π΅ΡˆΠΈΡ‚ΡŒ эту Π·Π°Π΄Π°Ρ‡Ρƒ Π·Π° Π»ΠΈΠ½Π΅ΠΉΠ½ΠΎΠ΅ врСмя с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ ΠΌΠ΅ΠΌΠΎΠΈΠ·Π°Ρ†ΠΈΠΈ, которая сохраняСт Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Ρ‹ ΡƒΠΆΠ΅ Ρ€Π΅ΡˆΠ΅Π½Π½Ρ‹Ρ… ΠΏΠΎΠ΄Π·Π°Π΄Π°Ρ‡.

def fibonacci(n, memo):
    if n in memo:
        return memo[n]
    if n <= 1:
        memo[n] = n
    else:
        memo[n] = fibonacci(n-1, memo) + fibonacci(n-2, memo)
    return memo[n]

2. Бамая длинная общая ΠΏΠΎΠ΄ΠΏΠΎΡΠ»Π΅Π΄ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΠ½ΠΎΡΡ‚ΡŒ

Π—Π°Π΄Π°Ρ‡Π° ΠΎ самой Π΄Π»ΠΈΠ½Π½ΠΎΠΉ ΠΎΠ±Ρ‰Π΅ΠΉ ΠΏΠΎΠ΄ΠΏΠΎΡΠ»Π΅Π΄ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΠ½ΠΎΡΡ‚ΠΈ (LCS) β€” это классичСская Π·Π°Π΄Π°Ρ‡Π° динамичСского программирования, которая Π²ΠΊΠ»ΡŽΡ‡Π°Π΅Ρ‚ Π² сСбя поиск самой Π΄Π»ΠΈΠ½Π½ΠΎΠΉ ΠΏΠΎΠ΄ΠΏΠΎΡΠ»Π΅Π΄ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΠ½ΠΎΡΡ‚ΠΈ, ΠΎΠ±Ρ‰Π΅ΠΉ для Π΄Π²ΡƒΡ… Π·Π°Π΄Π°Π½Π½Ρ‹Ρ… строк. ΠŸΠΎΠ΄ΠΏΠΎΡΠ»Π΅Π΄ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΠ½ΠΎΡΡ‚ΡŒ строки β€” это ΠΏΠΎΡΠ»Π΅Π΄ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΠ½ΠΎΡΡ‚ΡŒ символов, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ ΠΏΠΎΡΠ²Π»ΡΡŽΡ‚ΡΡ Π² строкС Π² ΠΎΠ΄Π½ΠΎΠΌ ΠΈ Ρ‚ΠΎΠΌ ΠΆΠ΅ порядкС, Π½ΠΎ Π½Π΅ ΠΎΠ±ΡΠ·Π°Ρ‚Π΅Π»ΡŒΠ½ΠΎ ΠΏΠΎΡΠ»Π΅Π΄ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΠ½ΠΎ.

def lcs(s1, s2):
    m, n = len(s1), len(s2)
    dp = [[0] * (n+1) for _ in range(m+1)]

    for i in range(1, m+1):
        for j in range(1, n+1):
            if s1[i-1] == s2[j-1]:
                dp[i][j] = dp[i-1][j-1] + 1
            else:
                dp[i][j] = max(dp[i-1][j], dp[i][j-1])

    return dp[m][n]

3. Π—Π°Π΄Π°Ρ‡Π° ΠΎ Ρ€ΡŽΠΊΠ·Π°ΠΊΠ΅

Π—Π°Π΄Π°Ρ‡Π° ΠΎ Ρ€ΡŽΠΊΠ·Π°ΠΊΠ΅ β€” это классичСская Π·Π°Π΄Π°Ρ‡Π° ΠΎΠΏΡ‚ΠΈΠΌΠΈΠ·Π°Ρ†ΠΈΠΈ, которая Π²ΠΊΠ»ΡŽΡ‡Π°Π΅Ρ‚ Π² сСбя поиск ΠΎΠΏΡ‚ΠΈΠΌΠ°Π»ΡŒΠ½ΠΎΠ³ΠΎ подмноТСства ΠΏΡ€Π΅Π΄ΠΌΠ΅Ρ‚ΠΎΠ² для ΡƒΠΏΠ°ΠΊΠΎΠ²ΠΊΠΈ Π² Ρ€ΡŽΠΊΠ·Π°ΠΊ с ΠΊΠΎΠ½Π΅Ρ‡Π½ΠΎΠΉ Π²ΠΌΠ΅ΡΡ‚ΠΈΠΌΠΎΡΡ‚ΡŒΡŽ, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΌΠ°ΠΊΡΠΈΠΌΠΈΠ·ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ Ρ†Π΅Π½Π½ΠΎΡΡ‚ΡŒ ΡƒΠΏΠ°ΠΊΠΎΠ²Π°Π½Π½Ρ‹Ρ… ΠΏΡ€Π΅Π΄ΠΌΠ΅Ρ‚ΠΎΠ².

def knapsack(W, wt, val, n):
    dp = [[0] * (W+1) for _ in range(n+1)]

    for i in range(1, n+1):
        for w in range(1, W+1):
            if wt[i-1] <= w:
                dp[i][w] = max(val[i-1] + dp[i-1][w-wt[i-1]], dp[i-1][w])
            else:
                dp[i][w] = dp[i-1][w]

    return dp[n][W]

4. РасстояниС Π›Π΅Π²Π΅Π½ΡˆΡ‚Π΅ΠΉΠ½Π° (Ρ€Π΅Π΄Π°ΠΊΡ†ΠΈΠΎΠ½Π½ΠΎΠ΅ расстояниС)

Π—Π°Π΄Π°Ρ‡Π° рСдактирования расстояния Π·Π°ΠΊΠ»ΡŽΡ‡Π°Π΅Ρ‚ΡΡ Π² Π½Π°Ρ…ΠΎΠΆΠ΄Π΅Π½ΠΈΠΈ минимального количСства ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΉ, Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΡ‹Ρ… для прСобразования ΠΎΠ΄Π½ΠΎΠΉ строки Π² Π΄Ρ€ΡƒΠ³ΡƒΡŽ. ДопустимыС ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ: вставка, ΡƒΠ΄Π°Π»Π΅Π½ΠΈΠ΅ ΠΈ Π·Π°ΠΌΠ΅Π½Π°.

def edit_distance(s1, s2):
    m, n = len(s1), len(s2)
    dp = [[0] * (n+1) for _ in range(m+1)]

    for i in range(m+1):
        for j in range(n+1):
            if i == 0:
                dp[i][j] = j
            elif j == 0:
                dp[i][j] = i
            elif s1[i-1] == s2[j-1]:
                dp[i][j] = dp[i-1][j-1]
            else:
                dp[i][j] = 1 + min(dp[i-1][j], dp[i][j-1], dp[i-1][j-1])

    return dp[m][n]

5. Π‘Π°ΠΌΡ‹ΠΉ большой подмассив

Π—Π°Π΄Π°Ρ‡Π° ΠΎ самом большом подмассивС Π·Π°ΠΊΠ»ΡŽΡ‡Π°Π΅Ρ‚ΡΡ Π² поискС Π½Π΅ΠΏΡ€Π΅Ρ€Ρ‹Π²Π½ΠΎΠ³ΠΎ подмассива Π² ΠΎΠ΄Π½ΠΎΠΌΠ΅Ρ€Π½ΠΎΠΌ массивС чисСл с наибольшСй суммой.

def max_subarray(arr):
    n = len(arr)
    max_sum = float('-inf')
    current_sum = 0

    for i in range(n):
        current_sum += arr[i]
        max_sum = max(max_sum, current_sum)
        current_sum = max(current_sum, 0)

    return max_sum
Π‘ΠΎΠ»ΡŒΡˆΠ΅ ΠΏΠΎΠ»Π΅Π·Π½Ρ‹Ρ… ΠΌΠ°Ρ‚Π΅Ρ€ΠΈΠ°Π»ΠΎΠ² Π²Ρ‹ Π½Π°ΠΉΠ΄Π΅Ρ‚Π΅ Π½Π° нашСм Ρ‚Π΅Π»Π΅Π³Ρ€Π°ΠΌ-ΠΊΠ°Π½Π°Π»Π΅ Β«Π‘ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ° питониста»

6. Π Π°Π·ΠΌΠ΅Π½ ΠΌΠΎΠ½Π΅Ρ‚

ΠŸΡ€ΠΎΠ±Π»Π΅ΠΌΠ° Ρ€Π°Π·ΠΌΠ΅Π½Π° ΠΌΠΎΠ½Π΅Ρ‚ Π²ΠΊΠ»ΡŽΡ‡Π°Π΅Ρ‚ Π² сСбя поиск количСства способов внСсти сдачу Π½Π° Π·Π°Π΄Π°Π½Π½ΡƒΡŽ сумму Π΄Π΅Π½Π΅Π³, ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡ Π·Π°Π΄Π°Π½Π½Ρ‹ΠΉ Π½Π°Π±ΠΎΡ€ Π½ΠΎΠΌΠΈΠ½Π°Π»ΠΎΠ² ΠΌΠΎΠ½Π΅Ρ‚.

def coin_change(coins, amount):
    dp = [float('inf')] * (amount+1)
    dp[0] = 0

    for i in range(1, amount+1):
        for coin in coins:
            if coin <= i:
                dp[i] = min(dp[i], dp[i-coin] + 1)

    return dp[amount] if dp[amount] != float('inf') else -1

7. Π£ΠΌΠ½ΠΎΠΆΠ΅Π½ΠΈΠ΅ Ρ†Π΅ΠΏΠΎΡ‡ΠΊΠΈ ΠΌΠ°Ρ‚Ρ€ΠΈΡ†

Π—Π°Π΄Π°Ρ‡Π° умноТСния Ρ†Π΅ΠΏΠΎΡ‡Π΅ΠΊ ΠΌΠ°Ρ‚Ρ€ΠΈΡ† Π·Π°ΠΊΠ»ΡŽΡ‡Π°Π΅Ρ‚ΡΡ Π² поискС ΠΎΠΏΡ‚ΠΈΠΌΠ°Π»ΡŒΠ½ΠΎΠ³ΠΎ способа умноТСния ряда ΠΌΠ°Ρ‚Ρ€ΠΈΡ†. Π­Ρ‚ΠΎ классичСский ΠΏΡ€ΠΈΠΌΠ΅Ρ€ динамичСского программирования, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ Π²ΠΎ ΠΌΠ½ΠΎΠ³ΠΈΡ… областях, Ρ‚Π°ΠΊΠΈΡ… ΠΊΠ°ΠΊ ΠΊΠΎΠΌΠΏΡŒΡŽΡ‚Π΅Ρ€Π½Π°Ρ Π³Ρ€Π°Ρ„ΠΈΠΊΠ°, числСнный Π°Π½Π°Π»ΠΈΠ· ΠΈ Π½Π°ΡƒΡ‡Π½Ρ‹Π΅ вычислСния.

def matrix_chain_order(p):
    n = len(p) - 1
    m = [[float('inf')] * n for _ in range(n)]
    s = [[0] * n for _ in range(n)]

    for i in range(n):
        m[i][i] = 0

    for l in range(2, n+1):
        for i in range(n-l+1):
            j = i + l - 1
            for k in range(i, j):
                q = m[i][k] + m[k+1][j] + p[i] * p[k+1] * p[j+1]
                if q < m[i][j]:
                    m[i][j] = q
                    s[i][j] = k

    return m, s

8. Бамая длинная Π²ΠΎΠ·Ρ€Π°ΡΡ‚Π°ΡŽΡ‰Π°Ρ ΠΏΠΎΠ΄ΠΏΠΎΡΠ»Π΅Π΄ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΠ½ΠΎΡΡ‚ΡŒ

ΠŸΡ€ΠΎΠ±Π»Π΅ΠΌΠ° самой Π΄Π»ΠΈΠ½Π½ΠΎΠΉ растущСй ΠΏΠΎΠ΄ΠΏΠΎΡΠ»Π΅Π΄ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΠ½ΠΎΡΡ‚ΠΈ (LIS) Π²ΠΊΠ»ΡŽΡ‡Π°Π΅Ρ‚ Π² сСбя поиск самой Π΄Π»ΠΈΠ½Π½ΠΎΠΉ ΠΏΠΎΠ΄ΠΏΠΎΡΠ»Π΅Π΄ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΠ½ΠΎΡΡ‚ΠΈ Π·Π°Π΄Π°Π½Π½ΠΎΠΉ ΠΏΠΎΡΠ»Π΅Π΄ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΠ½ΠΎΡΡ‚ΠΈ, которая строго возрастаСт. ΠŸΡ€ΠΎΠ±Π»Π΅ΠΌΠ° LIS ΠΈΠΌΠ΅Π΅Ρ‚ мноТСство Ρ€Π΅Π°Π»ΡŒΠ½Ρ‹Ρ… ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠΉ, Ρ‚Π°ΠΊΠΈΡ… ΠΊΠ°ΠΊ сТатиС Π΄Π°Π½Π½Ρ‹Ρ…, распознаваниС ΠΎΠ±Ρ€Π°Π·ΠΎΠ² ΠΈ Π±ΠΈΠΎΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ‚ΠΈΠΊΠ°.

def lis(arr):
    n = len(arr)
    dp = [1] * n

    for i in range(1, n):
        for j in range(i):
            if arr[i] > arr[j]:
                dp[i] = max(dp[i], dp[j] + 1)

    return max(dp)

9. Π—Π°Π΄Π°Ρ‡Π° коммивояТСра

Π—Π°Π΄Π°Ρ‡Π° коммивояТСра (TSP) Π·Π°ΠΊΠ»ΡŽΡ‡Π°Π΅Ρ‚ΡΡ Π² поискС ΠΊΡ€Π°Ρ‚Ρ‡Π°ΠΉΡˆΠ΅Π³ΠΎ Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΠ³ΠΎ ΠΌΠ°Ρ€ΡˆΡ€ΡƒΡ‚Π°, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ ΠΏΡ€ΠΎΡ…ΠΎΠ΄ΠΈΡ‚ Ρ‡Π΅Ρ€Π΅Π· Π·Π°Π΄Π°Π½Π½Ρ‹ΠΉ Π½Π°Π±ΠΎΡ€ Π³ΠΎΡ€ΠΎΠ΄ΠΎΠ² ΠΈ возвращаСтся Π² Π½Π°Ρ‡Π°Π»ΡŒΠ½Ρ‹ΠΉ Π³ΠΎΡ€ΠΎΠ΄. TSP β€” это классичСская Π·Π°Π΄Π°Ρ‡Π° ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ‚ΠΈΠΊΠΈ, которая ΠΈΠΌΠ΅Π΅Ρ‚ мноТСство Ρ€Π΅Π°Π»ΡŒΠ½Ρ‹Ρ… ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠΉ, Ρ‚Π°ΠΊΠΈΡ… ΠΊΠ°ΠΊ логистика, транспорт ΠΈ оптимизация сСти.

def tsp(graph, start):
    n = len(graph)
    visited = (1 << n) - 1
    memo = {}

    def dfs(node, visited):
        if visited == 0:
            return graph[node][start]

        if (node, visited) in memo:
            return memo[(node, visited)]

        ans = float('inf')
        for i in range(n):
            if visited & (1 << i):
                ans = min(ans, graph[node][i] + dfs(i, visited ^ (1 << i)))

        memo[(node, visited)] = ans
        return ans

    return dfs(start, visited)

10. 0-1 ЦСлочислСнноС ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅

Π—Π°Π΄Π°Ρ‡Π° цСлочислСнного программирования 0-1 Π²ΠΊΠ»ΡŽΡ‡Π°Π΅Ρ‚ Π² сСбя поиск ΠΎΠΏΡ‚ΠΈΠΌΠ°Π»ΡŒΠ½ΠΎΠ³ΠΎ Ρ€Π΅ΡˆΠ΅Π½ΠΈΡ для Π½Π°Π±ΠΎΡ€Π° Π΄Π²ΠΎΠΈΡ‡Π½Ρ‹Ρ… ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹Ρ… Ρ€Π΅ΡˆΠ΅Π½ΠΈΡ с ΡƒΡ‡Π΅Ρ‚ΠΎΠΌ Π½Π°Π±ΠΎΡ€Π° ΠΎΠ³Ρ€Π°Π½ΠΈΡ‡Π΅Π½ΠΈΠΉ. Π—Π°Π΄Π°Ρ‡Π° цСлочислСнного программирования 0-1 ΠΈΠΌΠ΅Π΅Ρ‚ мноТСство практичСских ΠΏΡ€ΠΈΠΌΠ΅Π½Π΅Π½ΠΈΠΉ, Ρ‚Π°ΠΊΠΈΡ… ΠΊΠ°ΠΊ распрСдСлСниС рСсурсов, составлСниС расписания ΠΈ производствСнноС ΠΏΠ»Π°Π½ΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅.

def knapsack(W, wt, val, n):
    dp = [[0] * (W+1) for _ in range(n+1)]

    for i in range(1, n+1):
        for w in range(1, W+1):
            if wt[i-1] <= w:
                dp[i][w] = max(val[i-1] + dp[i-1][w-wt[i-1]], dp[i-1][w])
            else:
                dp[i][w] = dp[i-1][w]

    return dp[n][W]

11. РасстояниС Π›Π΅Π²Π΅Π½ΡˆΡ‚Π΅ΠΉΠ½Π° с Ρ€Π°Π·Ρ€Π΅ΡˆΠ΅Π½Π½Ρ‹ΠΌΠΈ опСрациями

Π—Π°Π΄Π°Ρ‡Π° «РасстояниС Π›Π΅Π²Π΅Π½ΡˆΡ‚Π΅ΠΉΠ½Π°Β» ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ Ρ€Π°ΡΡˆΠΈΡ€Π΅Π½Π°, Ρ‡Ρ‚ΠΎΠ±Ρ‹ Ρ€Π°Π·Ρ€Π΅ΡˆΠΈΡ‚ΡŒ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½Π½Ρ‹ΠΉ Π½Π°Π±ΠΎΡ€ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΉ рСдактирования, Ρ‚Π°ΠΊΠΈΡ… ΠΊΠ°ΠΊ вставка, ΡƒΠ΄Π°Π»Π΅Π½ΠΈΠ΅ ΠΈ Π·Π°ΠΌΠ΅Π½Π°.

def edit_distance_with_allowed_ops(s1, s2, allowed_ops):
    m, n = len(s1), len(s2)
    dp = [[0] * (n+1) for _ in range(m+1)]

    for i in range(m+1):
        dp[i][0] = i

    for j in range(n+1):
        dp[0][j] = j

    for i in range(1, m+1):
        for j in range(1, n+1):
            if s1[i-1] == s2[j-1]:
                dp[i][j] = dp[i-1][j-1]
            elif allowed_ops.get((s1[i-1], s2[j-1])):
                op_cost = allowed_ops[(s1[i-1], s2[j-1])]
                dp[i][j] = min(dp[i-1][j] + op_cost[0], dp[i][j-1] + op_cost[1], dp[i-1][j-1] + op_cost[2])
            else:
                dp[i][j] = 1 + min(dp[i-1][j], dp[i][j-1], dp[i-1][j-1])

    return dp[m][n]

12. Бамая длинная палиндромная подстрока

Π—Π°Π΄Π°Ρ‡Π° «Бамая длинная палиндромная подстрока» Π·Π°ΠΊΠ»ΡŽΡ‡Π°Π΅Ρ‚ΡΡ Π² поискС самой Π΄Π»ΠΈΠ½Π½ΠΎΠΉ подстроки Π·Π°Π΄Π°Π½Π½ΠΎΠΉ строки, которая являСтся ΠΏΠ°Π»ΠΈΠ½Π΄Ρ€ΠΎΠΌΠΎΠΌ.

def longest_palindromic_substring(s):
    n = len(s)
    dp = [[False] * n for _ in range(n)]
    max_len = 1
    start = 0

    for i in range(n):
        dp[i][i] = True

    for l in range(2, n+1):
        for i in range(n-l+1):
            j = i + l - 1

            if l == 2:
                dp[i][j] = s[i] == s[j]
            else:
                dp[i][j] = s[i] == s[j] and dp[i+1][j-1]

            if dp[i][j] and l > max_len:
                max_len = l
                start = i

    return s[start:start+max_len]

13. Π—Π°Π΄Π°Ρ‡Π° ΠΎ подмассивС максимального произвСдСния (Maximum Product Subarray)

Π—Π°Π΄Π°Ρ‡Π° ΠΎ подмассивС максимального произвСдСния Π·Π°ΠΊΠ»ΡŽΡ‡Π°Π΅Ρ‚ΡΡ Π² поискС Π½Π΅ΠΏΡ€Π΅Ρ€Ρ‹Π²Π½ΠΎΠ³ΠΎ подмассива Π² ΠΎΠ΄Π½ΠΎΠΌΠ΅Ρ€Π½ΠΎΠΌ массивС чисСл с наибольшим ΠΏΡ€ΠΎΠΈΠ·Π²Π΅Π΄Π΅Π½ΠΈΠ΅ΠΌ.

def max_product_subarray(nums):
    n = len(nums)
    max_prod = nums[0]
    min_prod = nums[0]
    max_so_far = nums[0]

    for i in range(1, n):
        temp = max_prod
        max_prod = max(nums[i], max(nums[i] * max_prod, nums[i] * min_prod))
        min_prod = min(nums[i], min(nums[i] * temp, nums[i] * min_prod))
        max_so_far = max(max_so_far, max_prod)

    return max_so_far

14. Π‘Π°ΠΌΡ‹ΠΉ большой ΠΏΡ€ΡΠΌΠΎΡƒΠ³ΠΎΠ»ΡŒΠ½ΠΈΠΊ Π½Π° гистограммС

Π—Π°Π΄Π°Ρ‡Π° Β«Π‘Π°ΠΌΡ‹ΠΉ большой ΠΏΡ€ΡΠΌΠΎΡƒΠ³ΠΎΠ»ΡŒΠ½ΠΈΠΊ Π² гистограммС» Π²ΠΊΠ»ΡŽΡ‡Π°Π΅Ρ‚ Π² сСбя поиск самого большого ΠΏΡ€ΡΠΌΠΎΡƒΠ³ΠΎΠ»ΡŒΠ½ΠΈΠΊΠ°, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ сформирован Π½Π° гистограммС, состоящСй ΠΈΠ· ΠΏΡ€ΡΠΌΠΎΡƒΠ³ΠΎΠ»ΡŒΠ½ΠΈΠΊΠΎΠ² Ρ€Π°Π·Π½ΠΎΠΉ высоты.

def largest_rectangle_area(heights):
    n = len(heights)
    left = [0] * n
    right = [0] * n
    stack = []

    for i in range(n):
        while stack and heights[stack[-1]] >= heights[i]:
            stack.pop()

        left[i] = stack[-1] if stack else -1
        stack.append(i)

    stack = []
    for i in range(n-1, -1, -1):
        while stack and heights[stack[-1]] >= heights[i]:
            stack.pop()

        right[i] = stack[-1] if stack else n
        stack.append(i)

    max_area = 0
    for i in range(n):
        max_area = max(max_area, heights[i] * (right[i] - left[i] - 1))

    return max_area

15. БросаниС яиц

Π—Π°Π΄Π°Ρ‡Π° ΠΎ бросании яиц состоит Π² Ρ‚ΠΎΠΌ, Ρ‡Ρ‚ΠΎΠ±Ρ‹ Π½Π°ΠΉΡ‚ΠΈ минимальноС количСство ΠΏΠΎΠΏΡ‹Ρ‚ΠΎΠΊ, Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΡ‹Ρ… для опрСдСлСния самого высокого этаТа, с ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ³ΠΎ яйцо ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ ΡΠ±Ρ€ΠΎΡˆΠ΅Π½ΠΎ, Π½Π΅ Ρ€Π°Π·Π±ΠΈΠ²Π°ΡΡΡŒ.

def egg_drop(n, k):
    dp = [[0] * (k+1) for _ in range(n+1)]

    for i in range(1, n+1):
        dp[i][1] = 1
        dp[i][0] = 0

    for j in range(1, k+1):
        dp[1][j] = j

    for i in range(2, n+1):
        for j in range(2, k+1):
            dp[i][j] = float('inf')
            for x in range(1, j+1):
                res = 1 + max(dp[i-1][x-1], dp[i][j-x])
                dp[i][j] = min(dp[i][j], res)

    return dp[n][k]

16. ΠŸΠΎΠ΄ΡΡ‡Π΅Ρ‚ Π±ΠΈΡ‚ΠΎΠ²

Π—Π°Π΄Π°Ρ‡Π° подсчСта Π±ΠΈΡ‚ΠΎΠ² Π·Π°ΠΊΠ»ΡŽΡ‡Π°Π΅Ρ‚ΡΡ Π² Ρ‚ΠΎΠΌ, Ρ‡Ρ‚ΠΎΠ±Ρ‹ Π½Π°ΠΉΡ‚ΠΈ количСство Π΅Π΄ΠΈΠ½ΠΈΡ‡Π½Ρ‹Ρ… Π±ΠΈΡ‚ΠΎΠ² Π² Π΄Π²ΠΎΠΈΡ‡Π½ΠΎΠΌ прСдставлСнии ΠΊΠ°ΠΆΠ΄ΠΎΠ³ΠΎ числа ΠΎΡ‚ 0 Π΄ΠΎ n.

def count_bits(n):
    dp = [0] * (n+1)

    for i in range(1, n+1):
        dp[i] = dp[i >> 1] + (i & 1)

    return dp

17. Π˜Π΄Π΅Π°Π»ΡŒΠ½Ρ‹Π΅ ΠΊΠ²Π°Π΄Ρ€Π°Ρ‚Ρ‹

Π—Π°Π΄Π°Ρ‡Π° ΠΎ ΡΠΎΠ²Π΅Ρ€ΡˆΠ΅Π½Π½Ρ‹Ρ… ΠΊΠ²Π°Π΄Ρ€Π°Ρ‚Π°Ρ… Π·Π°ΠΊΠ»ΡŽΡ‡Π°Π΅Ρ‚ΡΡ Π² Ρ‚ΠΎΠΌ, Ρ‡Ρ‚ΠΎΠ±Ρ‹ Π½Π°ΠΉΡ‚ΠΈ минимальноС количСство ΡΠΎΠ²Π΅Ρ€ΡˆΠ΅Π½Π½Ρ‹Ρ… ΠΊΠ²Π°Π΄Ρ€Π°Ρ‚Π½Ρ‹Ρ… чисСл, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ Π² суммС Π΄Π°ΡŽΡ‚ Π·Π°Π΄Π°Π½Π½ΠΎΠ΅ число.

def num_squares(n):
    dp = [float('inf')] * (n+1)
    dp[0] = 0

    for i in range(1, n+1):
        j = 1
        while j*j <= i:
            dp[i] = min(dp[i], dp[i-j*j] + 1)
            j += 1

    return dp[n]

18. Π Π°Π·Π΄Π΅Π» Ρ€Π°Π²Π½ΠΎΠΉ суммы подмноТСства (Partition Equal Subset Sum)

ΠŸΡ€ΠΎΠ±Π»Π΅ΠΌΠ° Ρ€Π°Π²Π½ΠΎΠΉ суммы подмноТСств Ρ€Π°Π·Π΄Π΅Π»ΠΎΠ² Π²ΠΊΠ»ΡŽΡ‡Π°Π΅Ρ‚ Π² сСбя ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½ΠΈΠ΅ Ρ‚ΠΎΠ³ΠΎ, ΠΌΠΎΠΆΠ½ΠΎ Π»ΠΈ Ρ€Π°Π·Π±ΠΈΡ‚ΡŒ Π΄Π°Π½Π½Ρ‹ΠΉ Π½Π°Π±ΠΎΡ€ Π½Π° Π΄Π²Π° подмноТСства Ρ‚Π°ΠΊ, Ρ‡Ρ‚ΠΎΠ±Ρ‹ сумма элСмСнтов Π² ΠΎΠ±ΠΎΠΈΡ… подмноТСствах Π±Ρ‹Π»Π° ΠΎΠ΄ΠΈΠ½Π°ΠΊΠΎΠ²ΠΎΠΉ.

def can_partition(nums):
    n = len(nums)
    s = sum(nums)

    if s % 2 != 0:
        return False

    target = s // 2
    dp = [False] * (target+1)
    dp[0] = True

    for i in range(1, n+1):
        for j in range(target, nums[i-1]-1, -1):
            dp[j] |= dp[j-nums[i-1]]

    return dp[target]

19. Бамая длинная общая подстрока

Π—Π°Π΄Π°Ρ‡Π° «Бамая длинная общая подстрока» Π·Π°ΠΊΠ»ΡŽΡ‡Π°Π΅Ρ‚ΡΡ Π² поискС самой Π΄Π»ΠΈΠ½Π½ΠΎΠΉ подстроки, ΠΎΠ±Ρ‰Π΅ΠΉ для Π΄Π²ΡƒΡ… Π·Π°Π΄Π°Π½Π½Ρ‹Ρ… строк.

def longest_common_substring(s1, s2):
    m, n = len(s1), len(s2)
    dp = [[0] * (n+1) for _ in range(m+1)]
    max_len = 0

    for i in range(1, m+1):
        for j in range(1, n+1):
            if s1[i-1] == s2[j-1]:
                dp[i][j] = dp[i-1][j-1] + 1
                max_len = max(max_len, dp[i][j])

    return max_len

22. Π£Π½ΠΈΠΊΠ°Π»ΡŒΠ½Ρ‹Π΅ ΠΏΡƒΡ‚ΠΈ

ΠŸΡ€ΠΎΠ±Π»Π΅ΠΌΠ° ΡƒΠ½ΠΈΠΊΠ°Π»ΡŒΠ½Ρ‹Ρ… ΠΏΡƒΡ‚Π΅ΠΉ Π²ΠΊΠ»ΡŽΡ‡Π°Π΅Ρ‚ Π² сСбя поиск количСства ΡƒΠ½ΠΈΠΊΠ°Π»ΡŒΠ½Ρ‹Ρ… ΠΏΡƒΡ‚Π΅ΠΉ ΠΈΠ· Π²Π΅Ρ€Ρ…Π½Π΅Π³ΠΎ Π»Π΅Π²ΠΎΠ³ΠΎ ΡƒΠ³Π»Π° Π² Π½ΠΈΠΆΠ½ΠΈΠΉ ΠΏΡ€Π°Π²Ρ‹ΠΉ ΡƒΠ³ΠΎΠ» сСтки m x n, ΠΏΠΎ ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΌ Π²Ρ‹ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ Π΄Π²ΠΈΠ³Π°Ρ‚ΡŒΡΡ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Π²Π½ΠΈΠ· ΠΈΠ»ΠΈ Π²ΠΏΡ€Π°Π²ΠΎ.

def unique_paths(m, n):
    dp = [[0] * n for _ in range(m)]
    dp[0][0] = 1

    for i in range(m):
        for j in range(n):
            if i > 0:
                dp[i][j] += dp[i-1][j]
            if j > 0:
                dp[i][j] += dp[i][j-1]

    return dp[m-1][n-1]

23. РасстояниС Π›Π΅Π²Π΅Π½ΡˆΡ‚Π΅ΠΉΠ½Π° с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ Ρ€Π°Π·Ρ€Π΅ΡˆΠ΅Π½Π½Ρ‹Ρ… ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΉ

Π—Π°Π΄Π°Ρ‡Ρƒ «РасстояниС Π›Π΅Π²Π΅Π½ΡˆΡ‚Π΅ΠΉΠ½Π°Β» ΠΌΠΎΠΆΠ½ΠΎ Ρ€Π°ΡΡˆΠΈΡ€ΠΈΡ‚ΡŒ, Ссли ΠΌΡ‹ Ρ…ΠΎΡ‚ΠΈΠΌ Ρ€Π°Π·Ρ€Π΅ΡˆΠΈΡ‚ΡŒ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½Π½Ρ‹ΠΉ Π½Π°Π±ΠΎΡ€ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΉ рСдактирования, Ρ‚Π°ΠΊΠΈΡ… ΠΊΠ°ΠΊ вставка, ΡƒΠ΄Π°Π»Π΅Π½ΠΈΠ΅ ΠΈ Π·Π°ΠΌΠ΅Π½Π°.

def edit_distance_with_allowed_ops(s1, s2, allowed_ops):
    m, n = len(s1), len(s2)
    dp = [[0] * (n+1) for _ in range(m+1)]

    for i in range(m+1):
        dp[i][0] = i

    for j in range(n+1):
        dp[0][j] = j

    for i in range(1, m+1):
        for j in range(1, n+1):
            if s1[i-1] == s2[j-1]:
                dp[i][j] = dp[i-1][j-1]
            elif allowed_ops.get((s1[i-1], s2[j-1])):
                op_cost = allowed_ops[(s1[i-1], s2[j-1])]
                dp[i][j] = min(dp[i-1][j] + op_cost[0], dp[i][j-1] + op_cost[1], dp[i-1][j-1] + op_cost[2])
            else:
                dp[i][j] = 1 + min(dp[i-1][j], dp[i][j-1], dp[i-1][j-1])

    return dp[m][n]

24. ΠŸΡ€ΠΎΠ±Π»Π΅ΠΌΠ° суммы подмноТСства

ΠŸΡ€ΠΎΠ±Π»Π΅ΠΌΠ° суммы подмноТСства Π²ΠΊΠ»ΡŽΡ‡Π°Π΅Ρ‚ Π² сСбя ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½ΠΈΠ΅ Ρ‚ΠΎΠ³ΠΎ, сущСствуСт Π»ΠΈ подмноТСство Π·Π°Π΄Π°Π½Π½ΠΎΠ³ΠΎ Π½Π°Π±ΠΎΡ€Π° Ρ†Π΅Π»Ρ‹Ρ… чисСл, ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ΅ Π² суммС Π΄Π°Π΅Ρ‚ Π·Π°Π΄Π°Π½Π½ΡƒΡŽ сумму.

def subset_sum(nums, target):
    n = len(nums)
    dp = [[False] * (target+1) for _ in range(n+1)]

    for i in range(n+1):
        dp[i][0] = True

    for i in range(1, n+1):
        for j in range(1, target+1):
            if nums[i-1] <= j:
                dp[i][j] = dp[i-1][j-nums[i-1]] or dp[i-1][j]
            else:
                dp[i][j] = dp[i-1][j]

    return dp[n][target]

25. Бамая длинная палиндромная ΠΏΠΎΡΠ»Π΅Π΄ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΠ½ΠΎΡΡ‚ΡŒ

Π—Π°Π΄Π°Ρ‡Π° «Бамая длинная палиндромная ΠΏΠΎΠ΄ΠΏΠΎΡΠ»Π΅Π΄ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΠ½ΠΎΡΡ‚ΡŒΒ» Π²ΠΊΠ»ΡŽΡ‡Π°Π΅Ρ‚ Π² сСбя поиск самой Π΄Π»ΠΈΠ½Π½ΠΎΠΉ ΠΏΠΎΠ΄ΠΏΠΎΡΠ»Π΅Π΄ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΠ½ΠΎΡΡ‚ΠΈ Π·Π°Π΄Π°Π½Π½ΠΎΠΉ строки, которая являСтся ΠΏΠ°Π»ΠΈΠ½Π΄Ρ€ΠΎΠΌΠΎΠΌ.

def longest_palindromic_substring(s):
    n = len(s)
    dp = [[False] * n for _ in range(n)]
    max_len = 1
    start = 0

    for i in range(n):
        dp[i][i] = True

    for l in range(2, n+1):
        for i in range(n-l+1):
            j = i + l - 1

            if l == 2:
                dp[i][j] = s[i] == s[j]
            else:
                dp[i][j] = s[i] == s[j] and dp[i+1][j-1]

            if dp[i][j] and l > max_len:
                max_len = l
                start = i

    return s[start:start+max_len]

25. Π‘Π°ΠΌΡ‹ΠΉ большой ΠΏΡ€ΡΠΌΠΎΡƒΠ³ΠΎΠ»ΡŒΠ½ΠΈΠΊ Π½Π° гистограммС

Π—Π°Π΄Π°Ρ‡Π° Β«Π‘Π°ΠΌΡ‹ΠΉ большой ΠΏΡ€ΡΠΌΠΎΡƒΠ³ΠΎΠ»ΡŒΠ½ΠΈΠΊ Π² гистограммС» Π²ΠΊΠ»ΡŽΡ‡Π°Π΅Ρ‚ Π² сСбя поиск самого большого ΠΏΡ€ΡΠΌΠΎΡƒΠ³ΠΎΠ»ΡŒΠ½ΠΈΠΊΠ°, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ сформирован Π½Π° гистограммС, состоящСй ΠΈΠ· ΠΏΡ€ΡΠΌΠΎΡƒΠ³ΠΎΠ»ΡŒΠ½ΠΈΠΊΠΎΠ² Ρ€Π°Π·Π½ΠΎΠΉ высоты.

def largest_rectangle_area(heights):
    n = len(heights)
    left = [0] * n
    right = [0] * n
    stack = []

    for i in range(n):
        while stack and heights[stack[-1]] >= heights[i]:
            stack.pop()

        left[i] = stack[-1] if stack else -1
        stack.append(i)

    stack = []
    for i in range(n-1, -1, -1):
        while stack and heights[stack[-1]] >= heights[i]:
            stack.pop()

        right[i] = stack[-1] if stack else n
        stack.append(i)

    max_area = 0
    for i in range(n):
        max_area = max(max_area, heights[i] * (right[i] - left[i] - 1))

    return max_area

Π£Π½ΠΈΠΊΠ°Π»ΡŒΠ½Ρ‹Π΅ ΠΏΡƒΡ‚ΠΈ 2

Π—Π°Π΄Π°Ρ‡Π° Β«Π£Π½ΠΈΠΊΠ°Π»ΡŒΠ½Ρ‹Π΅ ΠΏΡƒΡ‚ΠΈ IIΒ» β€” это Ρ€Π°Π·Π½ΠΎΠ²ΠΈΠ΄Π½ΠΎΡΡ‚ΡŒ Π·Π°Π΄Π°Ρ‡ΠΈ Β«Π£Π½ΠΈΠΊΠ°Π»ΡŒΠ½Ρ‹Π΅ ΠΏΡƒΡ‚ΠΈΒ», Π² ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΉ Π½Π΅ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ ячСйки Π² сСткС Π·Π°Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²Π°Π½Ρ‹ ΠΈ ΠΏΠΎ Π½ΠΈΠΌ нСльзя ΠΏΡ€ΠΎΠΉΡ‚ΠΈ. Π—Π°Π΄Π°Ρ‡Π° состоит Π² Ρ‚ΠΎΠΌ, Ρ‡Ρ‚ΠΎΠ±Ρ‹ Π½Π°ΠΉΡ‚ΠΈ количСство ΡƒΠ½ΠΈΠΊΠ°Π»ΡŒΠ½Ρ‹Ρ… ΠΏΡƒΡ‚Π΅ΠΉ ΠΈΠ· Π²Π΅Ρ€Ρ…Π½Π΅Π³ΠΎ Π»Π΅Π²ΠΎΠ³ΠΎ ΡƒΠ³Π»Π° Π² Π½ΠΈΠΆΠ½ΠΈΠΉ ΠΏΡ€Π°Π²Ρ‹ΠΉ ΡƒΠ³ΠΎΠ» сСтки, Π³Π΄Π΅ Π²Ρ‹ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ Π΄Π²ΠΈΠ³Π°Ρ‚ΡŒΡΡ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Π²Π½ΠΈΠ· ΠΈΠ»ΠΈ Π²ΠΏΡ€Π°Π²ΠΎ ΠΈ Π½Π΅ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ Ρ…ΠΎΠ΄ΠΈΡ‚ΡŒ ΠΏΠΎ Π·Π°Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²Π°Π½Π½Ρ‹ΠΌ ячСйкам.

def unique_paths_with_obstacles(obstacle_grid):
    m, n = len(obstacle_grid), len(obstacle_grid[0])
    dp = [[0] * n for _ in range(m)]

    if obstacle_grid[0][0] == 0:
        dp[0][0] = 1

    for i in range(m):
        for j in range(n):
            if obstacle_grid[i][j] == 0:
                if i > 0:
                    dp[i][j] += dp[i-1][j]
                if j > 0:
                    dp[i][j] += dp[i][j-1]

    return dp[m-1][n-1]

Π—Π°ΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅

ДинамичСскоС ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ β€” это ΠΌΠΎΡ‰Π½Ρ‹ΠΉ инструмСнт, Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΡ‹ΠΉ для Ρ€Π΅ΡˆΠ΅Π½ΠΈΡ мноТСства слоТных Π·Π°Π΄Π°Ρ‡ спортивного программирования. Алгоритмы, обсуТдаСмыС Π² этом Π±Π»ΠΎΠ³Π΅, β€” лишь Π½Π΅ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ ΠΈΠ· ΠΌΠ½ΠΎΠ³ΠΈΡ… ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌ, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ ΠΌΠΎΠΆΠ½ΠΎ Ρ€Π΅ΡˆΠΈΡ‚ΡŒ с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ динамичСского программирования. Освоив эти Π°Π»Π³ΠΎΡ€ΠΈΡ‚ΠΌΡ‹ ΠΈ поняв Π»Π΅ΠΆΠ°Ρ‰ΠΈΠ΅ Π² ΠΈΡ… основС ΠΏΡ€ΠΈΠ½Ρ†ΠΈΠΏΡ‹, Π²Ρ‹ смоТСтС ΡΡ‚Π°Ρ‚ΡŒ Π±ΠΎΠ»Π΅Π΅ конкурСнтоспособным программистом ΠΈ Ρ€Π΅ΡˆΠ°Ρ‚ΡŒ Π±ΠΎΠ»Π΅Π΅ слоТныС Π·Π°Π΄Π°Ρ‡ΠΈ.

***

ΠœΠ°Ρ‚Π΅Ρ€ΠΈΠ°Π»Ρ‹ ΠΏΠΎ Ρ‚Π΅ΠΌΠ΅

Π˜ΡΡ‚ΠΎΡ‡Π½ΠΈΠΊΠΈ

Π›Π£Π§Π¨Π˜Π• БВАВЬИ ПО Π’Π•ΠœΠ•

admin
11 дСкабря 2018

ООП Π½Π° Python: ΠΊΠΎΠ½Ρ†Π΅ΠΏΡ†ΠΈΠΈ, ΠΏΡ€ΠΈΠ½Ρ†ΠΈΠΏΡ‹ ΠΈ ΠΏΡ€ΠΈΠΌΠ΅Ρ€Ρ‹ Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ

ΠŸΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ Π½Π° Python допускаСт Ρ€Π°Π·Π»ΠΈΡ‡Π½Ρ‹Π΅ ΠΌΠ΅Ρ‚ΠΎΠ΄ΠΎΠ»ΠΎΠ³ΠΈΠΈ, Π½ΠΎ Π² Π΅Π³ΠΎ основС...
admin
28 июня 2018

3 самых Π²Π°ΠΆΠ½Ρ‹Ρ… сфСры примСнСния Python: возмоТности языка

БущСствуСт мноТСство областСй примСнСния Python, Π½ΠΎ Π² Π½Π΅ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Ρ… ΠΎΠ½ особСнно...
admin
13 фСвраля 2017

ΠŸΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ Π½Π° Python: ΠΎΡ‚ Π½ΠΎΠ²ΠΈΡ‡ΠΊΠ° Π΄ΠΎ профСссионала

Пошаговая инструкция для всСх, ΠΊΡ‚ΠΎ Ρ…ΠΎΡ‡Π΅Ρ‚ ΠΈΠ·ΡƒΡ‡ΠΈΡ‚ΡŒΒ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ Π½Π° Python...