Módulo 10 - Memoização e a ideia da programação dinâmica

Subproblemas sobrepostos: a marca que pede a técnica

8 min de leitura · por Cesar Gargiulo, revisado pela equipe ValorFinal e GuardiaSec · Atualizado em 12/07/2026

O que você vai aprender

  • Reconhecer subproblemas sobrepostos num problema.
  • Entender subestrutura ótima: o todo montado a partir de partes.
  • Distinguir problemas que ganham de problemas que não ganham com memo.
  • Usar as duas marcas como um teste rápido de decisão.

As duas marcas de um problema de DP

Antes de sair memoizando tudo, vale saber quando a técnica ajuda. Ela paga o custo da tabela justamente cortando trabalho repetido, então só faz sentido quando existe trabalho repetido para cortar. Essa é a primeira marca, os subproblemas sobrepostos: quando você quebra o problema em partes menores, as mesmas partes voltam a aparecer, de novo e de novo. No Fibonacci isso é gritante, porque fib de 3 é pedido por vários galhos. Contar de quantos jeitos dá para subir uma escada, calcular o troco de um valor com certas moedas, contar caminhos numa grade: todos escondem essa repetição.

A segunda marca é a subestrutura ótima: a resposta do problema grande se monta a partir das respostas de problemas menores. No Fibonacci, fib de n é literalmente a soma de dois fib menores. Na escada, o número de jeitos de chegar a um degrau é a soma dos jeitos de chegar aos degraus de onde você consegue dar o último passo. Quando as duas marcas aparecem juntas, repetição de pedaços e montagem a partir de pedaços, você está diante de um problema feito sob medida para memoização e programação dinâmica. Reconhecer isso é metade da solução.

Diagrama comparando dois problemas. À esquerda, o Fibonacci: a árvore de quebra mostra os mesmos nós (fib de 2, fib de 3) circulados repetidos em galhos diferentes, com o rótulo subproblemas sobrepostos, serve para memo e DP. À direita, uma busca binária dividindo uma lista pela metade: cada metade é diferente da outra, nenhum pedaço se repete, com o rótulo subproblemas independentes, memo não ajuda.
À esquerda, os mesmos pedaços se repetem (serve memo). À direita, cada pedaço é único (não há repetição para cortar).

Quando a técnica não serve

Confundir os casos é comum, então vale olhar o outro lado. Muitos algoritmos também quebram o problema em partes, mas sem repetição. A busca binária corta a lista pela metade e joga uma das metades fora; a metade que sobra é sempre nova, nunca revisitada. O merge sort divide a lista em duas e ordena cada uma, mas as duas metades são pedaços diferentes da lista, sem sobreposição. Nesses casos, uma tabela de resultados não teria o que reusar, porque nada se repete. Dividir para conquistar não é o mesmo que subproblemas sobrepostos: o primeiro quebra em pedaços novos, o segundo esbarra nos mesmos pedaços.

🎮 Jogo da aula

Serve memo/DP ou não?

Classifique cada problema conforme ele tenha subproblemas sobrepostos (serve memo/DP) ou não.

Um teste rápido de decisão

Na prática, dá para decidir com duas perguntas. Primeira: se eu quebrar esse problema em versões menores dele mesmo, os mesmos pedaços vão reaparecer? Se a resposta é sim, há subproblemas sobrepostos e a memoização tem o que cortar. Segunda: a resposta que eu quero se monta a partir das respostas dos pedaços menores? Se sim, há subestrutura ótima e dá para construir a solução por partes. Quando as duas respostas são sim, memoização e programação dinâmica entram em cena. Quando o problema quebra em pedaços sempre novos, ou quando o todo não se monta a partir das partes, procure outra técnica.

Teste rápido

Qual característica de um problema indica que memoização e programação dinâmica vão ajudar?

Perguntas frequentes

O que são subproblemas sobrepostos, em uma frase?
São pedaços menores de um problema que reaparecem várias vezes quando você o quebra. No Fibonacci, fib de 3 é pedido por vários galhos diferentes. Essa repetição é o que a memoização corta: você calcula o pedaço uma vez e reusa nas próximas, em vez de refazer.
E o que é subestrutura ótima?
É a propriedade de a melhor resposta do problema grande poder ser montada a partir das melhores respostas dos pedaços menores. Se resolver as partes e combiná-las resolve o todo, o problema tem subestrutura ótima. Junto com os subproblemas sobrepostos, é o sinal de que a programação dinâmica se aplica.
Dividir para conquistar não é a mesma coisa?
Não. Dividir para conquistar (como o merge sort e a busca binária) quebra o problema em pedaços novos, que não se repetem. Programação dinâmica trata de pedaços que se repetem. Os dois quebram o problema, mas só a DP esbarra nos mesmos subproblemas, e é essa repetição que a memoização aproveita.
Se um problema tem repetição, uso sempre memoização?
Quase sempre vale, mas há um limite: se o número de subproblemas diferentes for gigantesco, a tabela pode não caber na memória. Nesses casos, existem variações que guardam só uma parte do cache. Ainda assim, para a esmagadora maioria dos problemas de escada, troco e grade, a memoização direta resolve.
Como reconheço rápido se um problema serve?
Faça duas perguntas: ao quebrar o problema, os mesmos pedaços voltam a aparecer? A resposta do todo se monta a partir das respostas das partes? Dois sins indicam memo e DP. Se o problema quebra em pedaços sempre novos, ou o todo não vem das partes, procure outra abordagem.
O problema do troco realmente tem essa marca?
Tem. Para dar o troco de um valor, você resolve o troco de valores menores, e esses valores menores reaparecem por caminhos diferentes de escolha de moedas. É repetição de subproblemas, e a resposta do valor cheio se monta a partir das respostas dos valores menores. Por isso o troco é um exemplo clássico de programação dinâmica.

Fontes

Seu progresso fica salvo neste aparelho. Assinantes sincronizam entre os aparelhos.