CodeGym /Cursos /Python SELF PT /Aplicação de DP em problemas reais

Aplicação de DP em problemas reais

Python SELF PT
Nível 60 , Lição 2
Disponível

7.1 Otimização de algoritmos dinâmicos.

A otimização de algoritmos dinâmicos foca na melhoria da eficiência de tempo e espaço. Existem várias abordagens de otimização, incluindo o uso de memoização, redução de memória utilizada e otimização da recursão.

1. Memoização:

Memoização é uma técnica onde os resultados dos cálculos são salvos para evitar cálculos repetidos da mesma sub-tarefa.

Exemplo:

No problema da troca de moedas, se você usar uma abordagem recursiva, pode salvar os resultados para as somas já calculadas para evitar cálculos repetidos.


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

2. Solução Tabelada (Bottom-Up):

A solução tabelada (bottom-up) constrói uma tabela de soluções para todas as possíveis sub-tarefas do caso base até o objetivo final. Isso evita os custos de chamadas recursivas.

Exemplo:

No problema da mochila, construindo uma tabela das quantidades mínimas de moedas para cada soma de 0 a S.


def fibonacci(n):
    dp = [0] * (n + 1)
    dp[1] = dp[2] = 1
    for i in range(3, n + 1):
        dp[i] = dp[i - 1] + dp[i - 2]
    return dp[n]
        
        

3. Redução do uso de memória:

Em alguns problemas, é possível otimizar o uso de memória, reduzindo o tamanho da tabela ou do array usado para armazenar resultados intermediários.

Exemplo:

No problema da mochila, pode-se usar um array unidimensional em vez de uma tabela bidimensional, se armazenar apenas as linhas correntes e anteriores.


def knapsack_optimized(weights, values, W):
    n = len(weights)
    dp = [0] * (W + 1)
    for i in range(n):
        for w in range(W, weights[i] - 1, -1):
            dp[w] = max(dp[w], dp[w - weights[i]] + values[i])
    return dp[W]
        
        

4. Recursão de cauda:

Recursão de cauda é uma chamada recursiva que ocorre no final da função. Isso permite que o compilador ou interpretador otimiza a pilha de chamadas.

Exemplo:

No problema de calcular os números de Fibonacci, pode-se usar recursão de cauda com um acumulador de resultado.

7.2 Aplicação de programação dinâmica em problemas reais.

A programação dinâmica é amplamente utilizada em várias áreas, incluindo ciência da computação, economia, bioinformática e pesquisa operacional. Aqui estão alguns exemplos de seu uso em problemas reais:

1. Otimização de rotas e logística:

Em problemas de logística e sistemas de transporte, a programação dinâmica é usada para encontrar rotas ótimas e minimizar custos.

Exemplo:

Problema do Caixeiro Viajante (Travelling Salesman Problem, TSP) — encontrar o caminho mais curto passando por todas as cidades.


def tsp(graph, start):
    n = len(graph)
    dp = [[None] * (1 << n) for _ in range(n)]

    def visit(city, visited):
        if visited == (1 << n) - 1:
            return graph[city][start]
        if dp[city][visited] is not None:
            return dp[city][visited]
        result = float('inf')
        for next_city in range(n):
            if visited & (1 << next_city) == 0:
                result = min(result, graph[city][next_city] + visit(next_city, visited | (1 << next_city)))
        dp[city][visited] = result
        return result

    return visit(start, 1 << start)

2. Alinhamento de sequências em bioinformática:

Na bioinformática, a programação dinâmica é usada para alinhar sequências de DNA, RNA e proteínas.

Exemplo:

Algoritmo de Needleman-Wunsch para alinhamento global de sequências e algoritmo de Smith-Waterman para alinhamento local.


def lcs(X, Y):
    m, n = len(X), len(Y)
    dp = [[0] * (n + 1) for _ in range(m + 1)]
    for i in range(1, m + 1):
        for j in range(1, n + 1):
            if X[i - 1] == Y[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. Cálculos financeiros e planejamento econômico:

A programação dinâmica é aplicada para otimizar portfólios de investimentos, gerenciamento de riscos e planejamento de produção.

Exemplo:

O problema da troca de moedas e o problema da mochila são usados para gerenciar ativos e alocar recursos de forma otimizada.

4. Gestão de estoques e produção:

Na produção e gestão de estoques, a programação dinâmica ajuda a otimizar processos e minimizar custos.

Exemplo:

Modelo de Gestão de Estoques para minimizar custos de armazenamento e pedido de produtos.

5. Aprendizado de máquina e inteligência artificial:

No aprendizado de máquina, a programação dinâmica é utilizada para otimizar algoritmos e encontrar ótimos globais.

Exemplo:

Algoritmos de aprendizado baseados em programação dinâmica, como o método de retropropagação em redes neurais.

Comentários
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION