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

1. Перекрывающиеся подзадачи. Задача может быть разделена на более мелкие подзадачи, и решения этих подзадач перекрываются или многократно используются повторно во время вычислений. Это свойство позволяет нам избежать избыточных вычислений, сохраняя решения подзадач и повторно используя их при необходимости.

2. Оптимальная подструктура: оптимальное решение задачи может быть построено из оптимальных решений ее подзадач. Это свойство позволяет нам итеративно строить решение, начиная с базовых случаев и комбинируя решения меньших подзадач для получения оптимального решения исходной задачи.

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

Редактировать проблему расстояния:

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

Вот псевдокод рекурсивного решения с перекрывающимися вызовами и экспоненциальным временем.

editDistance(str1, str2):

    // Base cases
    if str1 is empty:
        return length of str2
    
    if str2 is empty:
        return length of str1
    
    if last characters of str1 and str2 are the same:
        return editDistance(str1 without last character, str2 without last character)
    
    // Recursive calls
    return 1 + minimum of the following:
        - editDistance(str1 without last character, str2)    // Deletion
        - editDistance(str1, str2 without last character)    // Insertion
        - editDistance(str1 without last character, str2 without last character)    // Replacement

Решение для динамического программирования:

def editDistance(str1, str2):
    m = len(str1)
    n = len(str2)

    # Create a 2D matrix to store the edit distances
    dp = [[0] * (n + 1) for _ in range(m + 1)]

    # Initialize the first row and column of the matrix
    for i in range(m + 1):
        dp[i][0] = i
    for j in range(n + 1):
        dp[0][j] = j

    # Fill in the remaining cells of the matrix
    for i in range(1, m + 1):
        for j in range(1, n + 1):
            if str1[i - 1] == str2[j - 1]:
                dp[i][j] = dp[i - 1][j - 1]  # No operation required
            else:
                dp[i][j] = 1 + min(dp[i - 1][j],  # Deletion
                                   dp[i][j - 1],  # Insertion
                                   dp[i - 1][j - 1])  # Substitution

    # Return the minimum edit distance (bottom-right cell of the matrix)
    return dp[m][n]

# Example usage
str1 = "kitten"
str2 = "sitting"
distance = edit_distance(str1, str2)
print("Edit distance between", str1, "and", str2, "is", distance)

Проблема отбрасывания яиц:

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

Вот псевдокод рекурсивного решения с перекрывающимися вызовами и экспоненциальным временем.

eggDrop(eggs, floors):
    // Base cases
    if floors == 0 or floors == 1:
        return floors
    
    if eggs == 1:
        return floors
    
    // Initialize minimum attempts to a large value
    minAttempts = infinity
    
    // Recursive calls
    for i in range(1, floors + 1):
        attempts = 1 + max(eggDrop(eggs - 1, i - 1), eggDrop(eggs, floors - i))
        minAttempts = min(minAttempts, attempts)
    
    return minAttempts

Решение для динамического программирования:

def egg_drop(num_eggs, num_floors):
    # Create a 2D matrix to store the minimum attempts required
    dp = [[0] * (num_floors + 1) for _ in range(num_eggs + 1)]

    # Initialize the base cases
    for i in range(1, num_eggs + 1):
        dp[i][1] = 1  # If there's only one floor, one attempt is needed
        dp[i][0] = 0  # If there are no floors, no attempts are needed

    for j in range(1, num_floors + 1):
        dp[1][j] = j  # If there's only one egg, attempt all floors one by one

    # Fill in the remaining cells of the matrix
    for i in range(2, num_eggs + 1):
        for j in range(2, num_floors + 1):
            dp[i][j] = float('inf')  # Set initial minimum attempts to infinity

            for k in range(1, j + 1):
                # Calculate the maximum of two possibilities:
                # 1. Egg breaks -> Check below floors (i-1) eggs, (k-1) floors
                # 2. Egg doesn't break -> Check above floors (i) eggs, (j-k) floors
                # Add 1 for the current attempt
                attempts = 1 + max(dp[i - 1][k - 1], dp[i][j - k])

                # Update the minimum attempts if a better solution is found
                if attempts < dp[i][j]:
                    dp[i][j] = attempts

    # Return the minimum attempts (top-right cell of the matrix)
    return dp[num_eggs][num_floors]

# Example usage
num_eggs = 2
num_floors = 10
min_attempts = egg_drop(num_eggs, num_floors)
print("Minimum attempts required to find the critical floor:",
      min_attempts)

Целочисленная задача о рюкзаке:

Целочисленная задача о рюкзаке — это классическая задача оптимизации в математике и информатике, которая включает в себя максимизацию ценности или полезности предметов, упакованных в рюкзак, при соблюдении ограничений его веса или вместимости. Цель состоит в том, чтобы определить, какие предметы следует выбрать и упаковать в рюкзак, чтобы получить максимальную общую стоимость.

Псевдокод: рекурсивное решение с перекрывающимися вызовами и экспоненциальным временем.

knapsack(weight[], value[], capacity, n):
    if n == 0 or capacity == 0:
        return 0

    if weight[n-1] > capacity:
        return knapsack(weight, value, capacity, n-1)

    else:
        # Calculate the maximum value by either including or excluding the current item
        include = value[n-1] + knapsack(weight, value, capacity - weight[n-1], n-1)
        exclude = knapsack(weight, value, capacity, n-1)

        return max(include, exclude)

Решение для динамического программирования:

def knapsack_max_value(weights, values, capacity):
    n = len(weights)

    # Create a 2D matrix to store the maximum values
    dp = [[0] * (capacity + 1) for _ in range(n + 1)]

    # Fill in the matrix using a bottom-up approach
    for i in range(1, n + 1):
        for j in range(1, capacity + 1):
            if weights[i - 1] <= j:
                # Include the item and subtract its weight from the capacity
                # Compare the value of including the item with excluding it
                dp[i][j] = max(values[i - 1] + dp[i - 1][j - weights[i - 1]], dp[i - 1][j])
            else:
                # Item weight exceeds current capacity, exclude the item
                dp[i][j] = dp[i - 1][j]

    # Return the maximum value (bottom-right cell of the matrix)
    return dp[n][capacity]


# Example usage
weights = [3, 2, 4, 5]
values = [6, 8, 7, 10]
capacity = 9

max_value = knapsack_max_value(weights, values, capacity)
print("Maximum value that can be achieved:", max_value)

Самая длинная общая подпоследовательность:

Самая длинная общая подпоследовательность (LCS) — это понятие в информатике и математике, которое относится к самой длинной последовательности символов или элементов, которые имеют две или более строк или последовательностей.

Например, для строк «ABCD» и «ACDF» самой длинной общей подпоследовательностью будет «ACD», поскольку эти символы появляются в обеих строках и сохраняют свой относительный порядок.

Псевдокод рекурсивного решения с перекрывающимися вызовами и экспоненциальным временем.

longestCommonSubsequence(str1, str2, m, n):
    if m == 0 or n == 0:
        return 0

    if str1[m-1] == str2[n-1]:
        return 1 + longestCommonSubsequence(str1, str2, m-1, n-1)
    else:
        return max(longestCommonSubsequence(str1, str2, m-1, n), longestCommonSubsequence(str1, str2, m, n-1))

Решение для динамического программирования:

def longest_common_subsequence(str1, str2):
    m = len(str1)
    n = len(str2)

    # Create a 2D matrix to store the lengths of the common subsequences
    dp = [[0] * (n + 1) for _ in range(m + 1)]

    # Fill in the matrix using a bottom-up approach
    for i in range(1, m + 1):
        for j in range(1, n + 1):
            if str1[i - 1] == str2[j - 1]:
                # If characters match, increment the LCS length
                dp[i][j] = dp[i - 1][j - 1] + 1
            else:
                # Characters don't match, take the maximum of LCS lengths
                dp[i][j] = max(dp[i - 1][j], dp[i][j - 1])

    # Trace back and construct the LCS string
    lcs = ""
    i, j = m, n
    while i > 0 and j > 0:
        if str1[i - 1] == str2[j - 1]:
            # If characters match, add it to the LCS string
            lcs = str1[i - 1] + lcs
            i -= 1
            j -= 1
        elif dp[i - 1][j] > dp[i][j - 1]:
            # Move to the cell with a larger LCS length
            i -= 1
        else:
            j -= 1

    # Return the LCS length and the LCS string
    return dp[m][n], lcs


# Example usage
str1 = "AGGTAB"
str2 = "GXTXAYB"

length, lcs = longest_common_subsequence(str1, str2)
print("Length of Longest Common Subsequence:", length)
print("Longest Common Subsequence:", lcs)

Самая длинная общая подстрока:

Проблема самой длинной общей подстроки (LCS) — это понятие в информатике и обработке строк, которое включает в себя поиск самой длинной непрерывной подстроки, которая является общей для двух или более входных строк.

Псевдокод рекурсивного решения с перекрывающимися вызовами с экспоненциальным временем.

longestCommonSubstring(str1, str2, m, n, count):
    if m == 0 or n == 0:
        return count

    if str1[m-1] == str2[n-1]:
        count = longestCommonSubstring(str1, str2, m-1, n-1, count + 1)
    else:
        count = max(count, max(longestCommonSubstring(str1, str2, m-1, n, 0), longestCommonSubstring(str1, str2, m, n-1, 0)))

    return count

Решение для динамического программирования:

def longest_common_substring(str1, str2):
    m = len(str1)
    n = len(str2)

    # Create a 2D matrix to store the lengths of the common substrings
    dp = [[0] * (n + 1) for _ in range(m + 1)]

    # Variables to keep track of the maximum length and its ending position
    max_length = 0
    end_position = 0

    # Fill in the matrix using a bottom-up approach
    for i in range(1, m + 1):
        for j in range(1, n + 1):
            if str1[i - 1] == str2[j - 1]:
                # If characters match, increment the substring length
                dp[i][j] = dp[i - 1][j - 1] + 1
                if dp[i][j] > max_length:
                    # Update the maximum length and its ending position
                    max_length = dp[i][j]
                    end_position = i
            else:
                # Characters don't match, reset the substring length
                dp[i][j] = 0

    # Extract the longest common substring
    longest_substring = str1[end_position - max_length:end_position]

    # Return the maximum length and the longest common substring
    return max_length, longest_substring


# Example usage
str1 = "OldSite:GeeksforGeeks.org"
str2 = "NewSite:GeeksQuiz.com"

length, substring = longest_common_substring(str1, str2)
print("Length of Longest Common Substring:", length)
print("Longest Common Substring:", substring)

Самая длинная возрастающая подпоследовательность:

Самая длинная возрастающая подпоследовательность (LIS) — это понятие в информатике и математике, которое относится к самой длинной подпоследовательности данной последовательности, в которой элементы расположены в строго возрастающем порядке. Проблема LIS заключается в поиске этой самой длинной возрастающей подпоследовательности в заданной последовательности или массиве.

Например, для последовательности [4, 2, 8, 5, 9, 7] возможной самой длинной возрастающей подпоследовательностью будет [2, 5, 7, 9] с длиной 4. Эта подпоследовательность получается путем выбора элементов, которые соблюдать строгий порядок возрастания.

Псевдокод рекурсивного решения с перекрывающимися вызовами и экспоненциальным временем.

lis(arr, n):
    if n == 1:
        return 1

    maxEndingHere = 1
    for i in range(1, n):
        res = lis(arr, i)
        if arr[i-1] < arr[n-1] and res + 1 > maxEndingHere:
            maxEndingHere = res + 1

    return maxEndingHere

Решение для динамического программирования:

def longest_increasing_subsequence(nums):
    n = len(nums)

    # Create a list to store the lengths of the increasing subsequences
    dp = [1] * n

    # Iterate over the elements and fill in the list
    for i in range(1, n):
        for j in range(i):
            if nums[i] > nums[j]:
                # If the current element is greater, update the LIS length
                dp[i] = max(dp[i], dp[j] + 1)

    # Find the maximum LIS length
    max_length = max(dp)

    # Construct the LIS by tracing back the indices
    lis = []
    current_length = max_length
    for i in range(n - 1, -1, -1):
        if dp[i] == current_length:
            lis.append(nums[i])
            current_length -= 1

    # Reverse the LIS to get the correct order
    lis.reverse()

    # Return the maximum LIS length and the LIS itself
    return max_length, lis


# Example usage
sequence = [10, 22, 9, 33, 21, 50, 41, 60]
length, lis = longest_increasing_subsequence(sequence)
print("Length of Longest Increasing Subsequence:", length)
print("Longest Increasing Subsequence:", lis)

Самая длинная палиндромная последовательность:

Самая длинная палиндромная подпоследовательность (LPS) — это понятие в информатике и обработке строк, которое относится к самой длинной подпоследовательности заданной строки, являющейся палиндромом. Палиндром — это последовательность символов, которая одинаково читается вперед и назад.

Например, для строки «BBABCBCAB» возможной самой длинной палиндромной подпоследовательностью будет «BABCBAB», длина которой равна 7. Эта подпоследовательность получается путем выбора символов, образующих палиндром в исходной строке.

Псевдокод рекурсивного решения с перекрывающимися вызовами экспоненциального времени.

longestPalindromicSubsequence(str, start, end):
    if start > end:
        return 0

    if start == end:
        return 1

    if str[start] == str[end]:
        return longestPalindromicSubsequence(str, start+1, end-1) + 2
    else:
        return max(longestPalindromicSubsequence(str, start+1, end), longestPalindromicSubsequence(str, start, end-1))

Решение для динамического программирования:

def longest_palindromic_subsequence(string):
    n = len(string)

    # Create a 2D matrix to store the lengths of the palindromic subsequences
    dp = [[0] * n for _ in range(n)]

    # Initialize the base cases: each character is a palindrome of length 1
    for i in range(n):
        dp[i][i] = 1

    # Fill in the matrix using a bottom-up approach
    for length in range(2, n + 1):
        for i in range(n - length + 1):
            j = i + length - 1
            if string[i] == string[j]:
                # If the characters match, add 2 to the LPS length
                dp[i][j] = dp[i + 1][j - 1] + 2
            else:
                # If the characters don't match, take the maximum of LPS lengths
                dp[i][j] = max(dp[i + 1][j], dp[i][j - 1])

    # Return the length of the longest palindromic subsequence
    return dp[0][n - 1]


# Example usage
sequence = "character"
length = longest_palindromic_subsequence(sequence)
print("Length of Longest Palindromic Subsequence:", length)

Самая длинная битоническая последовательность:

Самая длинная битоническая подпоследовательность (LBS) — это понятие в информатике и динамическом программировании, которое относится к самой длинной подпоследовательности заданной последовательности, которая сначала увеличивается, а затем уменьшается или остается постоянной.

Например, для последовательности [1, 3, 5, 4, 2, 6, 3] одной из возможных длиннейших битонических подпоследовательностей является [1, 3, 5, 4, 3] с длиной 5. Эта подпоследовательность сначала увеличивает до пика в 5.

Псевдокод рекурсивного решения с перекрывающимися вызовами и экспоненциальным временем.

longestBitonicSubsequence(arr, n):
    if n == 0:
        return 0

    maxLen = 1
    for i in range(1, n):
        len1 = 0
        if arr[i] > arr[i-1]:
            len1 = longestBitonicSubsequence(arr, i)

        len2 = 0
        if arr[i] < arr[n-1]:
            len2 = longestBitonicSubsequence(arr, n-i)

        maxLen = max(maxLen, len1 + len2 + 1)

    return maxLen

Решение для динамического программирования:

def longest_bitonic_subsequence(arr):
    n = len(arr)

    # Create two arrays to store the longest increasing and decreasing subsequences
    lis = [1] * n
    lds = [1] * n

    # Compute the longest increasing subsequence (LIS) from left to right
    for i in range(1, n):
        for j in range(i):
            if arr[i] > arr[j]:
                lis[i] = max(lis[i], lis[j] + 1)

    # Compute the longest decreasing subsequence (LDS) from right to left
    for i in range(n - 2, -1, -1):
        for j in range(n - 1, i, -1):
            if arr[i] > arr[j]:
                lds[i] = max(lds[i], lds[j] + 1)

    # Find the maximum length of the bitonic subsequence
    max_length = 0
    for i in range(n):
        length = lis[i] + lds[i] - 1
        max_length = max(max_length, length)

    # Return the maximum length of the bitonic subsequence
    return max_length


# Example usage
sequence = [1, 11, 2, 10, 4, 5, 2, 1]
length = longest_bitonic_subsequence(sequence)
print("Length of Longest Bitonic Subsequence:", length)

Проблема суммы подмножества:

Задача о сумме подмножеств — известная вычислительная проблема в информатике и математике. Он включает в себя определение того, существует ли подмножество элементов из заданного набора, сумма которых равна заданному целевому значению.

Например, учитывая набор {2, 4, 6, 9} и целевую сумму 13, проблема суммы подмножества спрашивает, существует ли подмножество данного набора, сумма элементов которого равна 13. В этом случае ответ будет да, так как подмножество {4, 9} в сумме дает целевую сумму 13.

Псевдокод рекурсивного решения с перекрывающимися вызовами и экспоненциальным временем.

subsetSum(nums, target, index):

    // Base cases
    if target == 0:
        return true
    
    if index >= length of nums:
        return false
    
    // Recursive calls
    if nums[index] <= target:
        // Include the current number
        if subsetSum(nums, target - nums[index], index + 1) is true:
            return true
    
    // Exclude the current number
    if subsetSum(nums, target, index + 1) is true:
        return true
    
    // No subset found
    return false

Решение для динамического программирования:

def subset_sum(nums, target):
    n = len(nums)

    # Create a 2D matrix to store the subset sum possibilities
    dp = [[False] * (target + 1) for _ in range(n + 1)]

    # Base case: If the target is 0, an empty subset can achieve it
    for i in range(n + 1):
        dp[i][0] = True

    # Fill in the matrix using a bottom-up approach
    for i in range(1, n + 1):
        for j in range(1, target + 1):
            if nums[i - 1] > j:
                # If the current number is greater than the target, skip it
                dp[i][j] = dp[i - 1][j]
            else:
                # Consider two possibilities: including or excluding the current number
                dp[i][j] = dp[i - 1][j] or dp[i - 1][j - nums[i - 1]]

    # Return True if a subset with the given target sum exists
    return dp[n][target]


# Example usage
numbers = [3, 34, 4, 12, 5, 2]
target_sum = 9
exists = subset_sum(numbers, target_sum)
if exists:
    print("Subset with the target sum exists.")
else:
    print("Subset with the target sum does not exist.")

Максимальная сумма увеличивающейся подпоследовательности:

Задача о возрастании подпоследовательности с максимальной суммой (MSIS) представляет собой разновидность классической задачи поиска самой длинной возрастающей подпоследовательности. Вместо определения длины самой длинной возрастающей подпоследовательности задача MSIS стремится найти подпоследовательность с максимальной суммой среди всех возрастающих подпоследовательностей в заданной последовательности.

Например, для данной последовательности [4, 6, 1, 3, 8, 4, 9] одной возможной максимальной возрастающей подпоследовательностью является [4, 6, 8, 9] с суммой 27. Эта подпоследовательность представляет возрастающую элементов с максимальной общей суммой в исходной последовательности.

Псевдокод рекурсивного решения с перекрывающимися вызовами и экспоненциальным временем.

maxSumIncreasingSubsequence(arr, n):
    if n == 1:
        return arr[0]

    maxSum = arr[n-1]
    for i in range(n-2, -1, -1):
        currentSum = maxSumIncreasingSubsequence(arr, i)
        if arr[i] < arr[n-1] and currentSum + arr[i] > maxSum:
            maxSum = currentSum + arr[i]

    return maxSum

Решение для динамического программирования:

def max_sum_increasing_subsequence(nums):
    n = len(nums)

    # Create a list to store the maximum sum increasing subsequences
    dp = nums[:]

    # Compute the maximum sum increasing subsequence
    for i in range(1, n):
        for j in range(i):
            if nums[i] > nums[j] and dp[i] < dp[j] + nums[i]:
                dp[i] = dp[j] + nums[i]

    # Find the maximum sum in the dp list
    max_sum = max(dp)

    # Return the maximum sum
    return max_sum


# Example usage
sequence = [1, 101, 2, 3, 100, 4, 5]
max_sum = max_sum_increasing_subsequence(sequence)
print("Maximum Sum Increasing Subsequence:", max_sum) 

Проблема с обменом монет:

Проблема сдачи монет — это классическая алгоритмическая задача, которая включает определение количества способов внести сдачу на заданную сумму денег с использованием определенного набора номиналов монет.

Цель состоит в том, чтобы найти общее количество уникальных способов внести сдачу на целевую сумму, используя заданные монеты.

Например, рассмотрим следующий сценарий:

• Целевая сумма: 5 долларов США.

• Номиналы монет: [1, 2, 5]

В этом случае есть несколько способов внести сдачу на 5 долларов:

• 5 однодолларовых монет

• 2 двухдолларовые монеты и 1 однодолларовая монета

• 1 пятидолларовая монета

Задача о смене монет требует найти все различные комбинации монет, которые в сумме дают целевую сумму.

Псевдокод рекурсивного решения с перекрывающимися рекурсивными вызовами и экспоненциальным временем.

coin_change(coins, amount):
    if amount == 0:
        return 1
    if amount < 0 or len(coins) == 0:
        return 0
    return coin_change(coins, amount - coins[-1]) + coin_change(coins[:-1], amount)

Решение для динамического программирования:

def coin_change(coins, amount):
    # Create a table to store the number of ways to make change for amounts 0 to amount
    dp = [0] * (amount + 1)
    dp[0] = 1

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

    return dp[amount]

# Example usage:
coins = [1, 2, 5]
target_amount = 5
num_ways = coin_change(coins, target_amount)
print("Number of ways to make change:", num_ways)

Проблема резки стержня:

Задача о перерезании стержня — классическая задача оптимизации в информатике и математике. Проблема состоит в том, чтобы определить лучший способ разрезать стержень заданной длины на более мелкие части, чтобы максимизировать общую стоимость или прибыль.

Псевдокод рекурсивного решения с перекрывающимися вызовами и экспоненциальным временем:

cut_rod(price, n):
    if n <= 0:
        return 0
    max_val = float('-inf')
    for i in range(n):
        max_val = max(max_val, price[i] + cut_rod(price, n - i - 1))
    return max_val

Решение для динамического программирования:

def cut_rod(price, n):
    # Create a list to store the optimal values for rod lengths 0 to n
    dp = [0] * (n + 1)
    
    for i in range(1, n + 1):
        max_val = float('-inf')
        for j in range(i):
            max_val = max(max_val, price[j] + dp[i - j - 1])
        dp[i] = max_val
    
    return dp[n]

# Example usage:
price = [1, 5, 8, 9, 10, 17, 17, 20]
rod_length = 4
max_profit = cut_rod(price, rod_length)
print("Maximum profit for rod length", rod_length, "is:", max_profit)

Задача умножения матриц:

Задача умножения матриц заключается в перемножении двух матриц для получения результирующей матрицы. Для двух матриц A и B, где количество столбцов в матрице A равно количеству строк в матрице B, цель состоит в том, чтобы вычислить матрицу произведения C.

Результирующая матрица C имеет размеры M x N, где M — количество строк в матрице A, а N — количество столбцов в матрице B. Элемент (i, j) матрицы C вычисляется путем скалярного произведения i-я строка матрицы A и j-й столбец матрицы B.

Например, рассмотрим следующие матрицы:

Матрица А:

[ 1. 2. 3 ]

[ 4. 5. 6 ]

Матрица Б:

[ 7. 8 ]

[ 9 10 ]

[11 12 ]

Результирующая матрица C будет:

[ 58. 64 ]

[139 154 ]

Чтобы вычислить каждый элемент результирующей матрицы C, мы берем скалярное произведение соответствующей строки в матрице A и столбца в матрице B. Например, элемент в позиции (1, 1) в C вычисляется как (1 * 7) + (2 * 9) + (3 * 11) = 58.

Псевдокод рекурсивного решения:

matrix_multiplication(A, B):
    if dimensions of A and B are compatible for multiplication:
        Create a result matrix C with appropriate dimensions

        if A and B are 1x1 matrices:
            C[0][0] = A[0][0] * B[0][0]
        else:
            Divide matrices A and B into submatrices
            Recursively compute subproducts:
            C11 = matrix_multiplication(A11, B11) + matrix_multiplication(A12, B21)
            C12 = matrix_multiplication(A11, B12) + matrix_multiplication(A12, B22)
            C21 = matrix_multiplication(A21, B11) + matrix_multiplication(A22, B21)
            C22 = matrix_multiplication(A21, B12) + matrix_multiplication(A22, B22)

            Combine subproducts into result matrix C
            
        return C
    else:
        Return an error indicating incompatible matrix dimensions

Решение для динамического программирования:

def matrix_chain_multiplication(dimensions):
    n = len(dimensions) - 1
    dp = [[0] * n for _ in range(n)]

    for length in range(2, n + 1):
        for i in range(1, n - length + 2):
            j = i + length - 1
            dp[i][j] = float('inf')

            for k in range(i, j):
                cost = dp[i][k] + dp[k + 1][j] + dimensions[i - 1] * dimensions[k] * dimensions[j]
                if cost < dp[i][j]:
                    dp[i][j] = cost

    return dp[1][n]