Como resolver problemas em um tabuleiro de 1x100 quadrados
Tabuleiros 1xN aparecem em provas de olimpíada, em entrevistas técnicas e às vezes em problemas de programação competitiva. A coisa mais importante a entender logo de cara é que a dimensão única elimina quase toda a complexidade geométrica, mas cria armadilhas recursivas que confundem muita gente. A maioria dos problemas envolve cobrir o tabuleiro com dominós, colocar peças sem que se toquem, ou calcular probabilidades de posicionamento. Vamos direto ao que funciona.
Contando caminhos em um tabuleiro de 1x100 quadrados
O problema mais básico que aparece recorrentemente pede para contar quantos caminhos existem indo do quadrado 1 ao quadrado 100, onde cada passo avança 1 ou 2 casas. Isso é uma sequência de Fibonacci disfarçada. O número de caminhos para o quadrado n é F(n), onde F(1)=1, F(2)=2, F(3)=3, F(4)=5 e assim por diante. Para n=100, o resultado é F(100), que é 354.224.848.179.261.915.075 — um número que cabe confortavelmente em um inteiro de 64 bits se você estiver usando Python, mas que estoura um int32 comum em C++. Quando eu comecei a trabalhar com isso, errei feio calculando F(100) com recursão pura. O programa simplesmente travou porque reCalculava os mesmos subresultados repetidamente. A solução é memoização ou iteração bottom-up. Eu uso um laço simples que mantém apenas os dois últimos valores, o que reduz o espaço de O(n) para O(1) e o tempo para linear. Em prática, isso roda em menos de 1 milissegundo.
Problemas de cobertura com dominós
Um domínio padrão cobre exatamente 2 quadrados adjacentes. A pergunta clássica é: dá para cobrir completamente um tabuleiro 1x100 com dominós? Sim, porque 100 é par. Existem 2^(n/2) maneiras de fazer isso de forma trivial quando o tabuleiro é 1xN, já que cada dominó é forçado a se alinhar na mesma direção. Mas se removermos dois quadrados opostos das extremidades — digamos, o quadrado 1 e o quadrado 100 — ainda sobram 98 quadrados, que é par, e ainda é perfeitamente cobrível. O problema só fica interessante quando removemos dois quadrados de cores diferentes em versões com tabuleiros xadrez coloridos, mas em 1xN a coloração não tem a mesma restrição de paridade porque todos os dominós cabem numa linha reta. O erro que vejo todo mundo cometer é achar que remover quaisquer dois quadrados deixa o tabuleiro cobrível. Se removermos o quadrado 50 e o 51 de um 1x100, sobram dois segmentos de 49 quadrados cada. 49 é ímpar, então nenhum dos dois segmentos pode ser coberto por dominós. O tabuleiro fica impossível de cobrir, mesmo com 98 quadrados restantes. Esse tipo de edge-case aparece com frequência em perguntas de entrevista.
Posicionar peças sem contato
Quantas maneiras existem de colocar k peças indistinguíveis em um tabuleiro 1x100 de forma que nenhuma fique adjacency? Isso é combinatória básica: você precisa de pelo menos um espaço vazio entre cada par de peças. O número de maneiras é C(100-k+1, k). Para k=10, por exemplo, seria C(91, 10) = 5.177.744.238.773. Esse fórmula funciona porque você pode transformar o problema em escolher k posições entre 100-k+1 espaços após compressão dos requisitos de separação. Já vi gente tentar resolver isso com backtracking ingênuo. Para k=10 em 100 casas, o backtracking puro leva segundos ou até minutos dependendo da implementação. A fórmula combinatória dá o resultado instantaneamente. A regra geral é: sempre que o tabuleiro for 1D, procure uma transformação combinatória antes de escrever qualquer recursão.
Probabilidade e posicionamento aleatório
Coloque uma peça em um quadrado escolhido uniformemente ao acaso em um tabuleiro 1x100. Qual a probabilidade de que ela não tenha vizinhos ocupados quando você adicionar uma segunda peça também aleatória? A resposta depende se as peças são distinguíveis ou não, mas o cálculo é direto. Para a primeira peça na posição i, o número de posições proibidas para a segunda é no máximo 2 (vizinhos esquerda e direita), exceto nas extremidades onde é 1. Média ponderada sobre todas as posições daria probabilidade de (100 - E[vizinhos]) / 99 para a segunda peça não cair adjacente. Isso parece simples até você introduzir três ou mais peças e pedir probabilidade de configuração sem adjacências. Aí a coisa vira inclusão-exclusão ou recorrência, e os números crescem rápido. Eu já gastfei horas depurando um simulador Monte Carlo que ia dar resultados consistentes, e o problema era que a amostragem rejeitando configurações com adjacências tinha taxa de aceitação muito baixa para N grande, tornando a convergência lenta demais para ser útil.
👉 Clique no botão abaixo para saber mais sobre o assunto!
Implementação prática
Se você está implementando isso em código, evite recursão sem memoização. Use iteração. Para sequências como Fibonacci, mantenha só as duas últimas variáveis. Para contagem combinatória, calcule fatores de forma incremental para evitar overflow em linguagens com tipos fixos. Em Python isso não é problema. Em C ou Java, use long ou BigInteger conforme necessário. Aqui vai um esboço rápido do approach iterativo para caminhos:
var prev2 = 1; var prev1 = 2; for (int i = 3; i
= n; i++) { var current = prev1 + prev2; prev2 = prev1; prev1 = current; } return prev1; Para combinações C(n, k), calcule como produto de k termos dividido por k fatorial, fazendo simplificação incremental para manter os valores intermediários menores.
Limitações e onde isso falha
Tabuleiros 1xN são úteis como pedagogia e para problemas de competição, mas a simplicidade dimensional é também sua limitação. Técnicas que funcionam perfeitamente em 1D colapsam em 2D. Por exemplo, a contagem de coberturas com dominós em 1xN tem fórmula fechada simples, mas em 2xN a situação já exige matrizes de transferência. Não tente generalizar os atalhos 1D para dimensões superiores. Outro ponto: problemas de contagem em 1x100 com restrições adicionais (como peças que pulam posições específicas, ou movimentos com saltos variados) podem rapidamente exigir programação dinâmica com estado expandido. Aí o ganho de simplicidade do 1D some e você precisa tratar tabelas de tamanho considerável. Para n=100 ainda cabe na memória, mas se o estado crescer para pares de posições ou configurações de blocos, os custos sobem.
Dicas do dia a dia
Identifique o tipo de problema antes de calcular: é Fibonacci, combinação, inclusão-exclusão ou DP. Teste com N pequeno (10, 20) para validar antes de rodar em 100. Sempre verifique paridade — metade dos problemas impossíveis que vejo people tentarem resolver são só casos onde a paridade já condena a solução desde o início. E não esqueça de checar as bordas do tabuleiro, porque é onde a maioria dos cálculos ingênuos erra.