Aula por Caique Paiva
Conhecimento Prévio Necessário:
Introdução
O objetivo da aula vai ser apresentar a ideia de DP em intervalo (range DP, em inglês) e resolver o seguinte problema (Leia o artigo antes de pensar nele):
Você tem uma string de tamanho . Também temos perguntas para responder, que são descritas por dois inteiros . A resposta é a quantidade de palíndromos no intervalo da string.
Uma string é dita palíndroma se ela é lida da mesma maneira da esquerda para direita. Por exemplo é palindromo, mas não é.
Input
A primeira linha tem uma string (). A segunda linha contém um inteiro (), o número de perguntas. As próximas linhas contém as perguntas. A -ésima linha contém dois inteiros , a descrição da -ésima pergunta.
Imprima inteiros, as respostas das perguntas.
Exemplo
Entrada | Saída |
caaaba 5 1 1 1 4 2 3 4 6 4 5 |
1 7 3 4 2 |
DP em Range
Imagine um problema que temos um vetor , e queremos responder perguntas de intervalos desse vetor. Além disso, temos a seguinte propiedade
- Conseguimos calcular a resposta da pergunta do intervalo com as respostas dos intervalos e , com variando de até .
Então, a ideia é fazer uma nisso! Os estados da seriam dois valores , que significa a resposta para a pergunta do intervalo . Para fazermos uma , precisamos de 3 coisas:
- Caso base: Normalmente o caso de intervalos , ou seja, com só um valor no intervalo, são fáceis e podem ser feitos na mão, ou seja, temos como os casos bases as .
- Transição: Para calcular , como dito acima, usamos os valores de e .
- Resposta final: Retornamos , que é a resposta da pergunta.
Como é só uma ideia abstrata, podemos adaptar algumas dessas ideias para cada problema, como vocês vão ver abaixo. Além disso, temos um total de intervalos em um vetor de tamanho , e também, na transição nós usamos valores para calcular , então, normalmente uma dp em range roda em .
Problema Inicial
Dado um retângulo , sua tarefa é corta-lo em quadradros. Em cada movimento, você pode selecionar um retângulo e corta-lo em dois retângulos de modo que os lados continuam inteiros. Qual é o mínimo número possível de movimentos?
Limites
Input
O input tem dois inteiros e .
Output
Imprima a menor quantidade possível de movimentos
Entrada | Saída |
3 5 |
3 |
Nota
A solução seria:As operações seriam: dividir o por um e , e então dividir o em e , e para finalizar dividir o em e .
Vamos fazer para ser a quantidade de operações para resolver o problema para um retângulo .
Caso base: , pois ele já é um quadrado
A transição vai ser
Isso é verdade pois estamos simulando construir uma linha que divida o retângulo em dois. Ou seja, se temos o retângulo de lados e vamos dividir esse retângulo por uma reta que corta o lado de tamanho em e , então basta resolvermos o problema para o retângulo da maneira mais rápida possivel, e o outro retângulo que sobra é o , que também temos que resolver da maneira mais rápida possivel, então, nesse caso, gastamos operações. Testando todas as divisões possíveis que nós conseguimos fazer, chegaremos na resposta mínima!
Veja que essa solução roda em (temos dp para calcular e cada dp tem uma transição de ). Segue o código para melhor entendimento (Link).
Certo, vamos para outro problema antes de ir para o problema do começo da aula.
Problema Médio
Lobo adora jogar jogos no seu celular. Ele está bem animado com o seguinte jogo:
Tem uma sequência de inteiros positivos, com todos eles entre ( e ). Lobo pode pegar dois números consecutivos com valores iguais e trocar eles por um único número com o valor uma unidade maior (Por exemplo, ele pode pegar dois números 7 e trocar por um 8). O objetivo é maximizar o valor do maior número no final do jogo.
Dado uma configuração inicial do jogo, diga qual é o maior número que o lobo consegue alcançar.
Limites:
Input
A primeira linha do input tem , e as próximas linhas dá a sequência de números do começo do jogo.
Output
Ache o maior inteiro que o Lobo consegue gerar.
Entrada | Saída |
4 1 1 1 2 |
3 |
Nota
Nesse exemplo, o Lobo pode juntar o segundo e o terceiro para obter a sequência , e então juntar os dois em um .
Vamos definir a da seguinte forma:
Se não consegumos transformar todos os números em só um no intervalo .
Caso contrário, onde é o maior número que consegumos gerar.
Então, os casos bases seriam onde é a sequência de números que o problema dá. Portanto, o algoritmo para calcular seria
Começe inicializando ., e então repita o seguinte algoritmo, começando com e indo até .
Se e dp , isso significa que conseguimos transformar em um número só, também, e eles são o mesmo número! Ou seja, fazendo as operações, conseguimos transformar em , basta transformar em , fazer a mesma coisa para , e juntar os dois. Logo, a resposta de .
(Detalhe: Veja que, se em nenhum momento conseguimos transformar em um cara só, , pois não entramos na condição do algoritimo em nenhum momento, e nós inicializamos ).
Então, no final, retornamos o maior valor que está na matriz . Esse algoritmo roda em (Temos intervalos para calcular e, para cada intervalo, fazemos operações para calcular ele). Segue o código para melhor entendimento (Link).
Certo, vamos para o problema do começo da aula agora!!
Problema Difícil
O enunciado está no começo da aula.
Seja a quantidade de palíndromos no intervalo , além disso, seja uma função que retorna 1 se o intervalo é palíndromo, e 0 caso contrário. Também vamos fazer como uma dp. Primeiro, vamos calcular .
Veja que , pois é só uma letra, então lida da esquerda para direita continua a mesma coisa. Agora, se no intervalo , se , então não é um palíndromo. Agora, se , basta ver agora se é um palíndromo, que está calculado em , então, a fórmula fica da seguinte maneira.
Perfeito!! Agora com pal calculado, vamos calcular a . Primeiro, veja que se um palindromo está no intervalo , então ele está em , além disso, se um palíndromo está em , então ele está em . Agora, os palíndromos se são contados duas vezes em e em são os que estão em e em ao mesmo tempo, ou seja, os que estão em . Agora, a única subsequência que não foi contada foi a que não está em e em , ou seja, o intervalo . Portanto, a resposta de vai ser
Que são todos os palíndromos em , em , porém nós contamos os palíndromos de duas vezes, portanto temos que tirar eles uma vez para eles serem contados só uma vez!! (Essa ideia se chama de princípio da inclusão-exclusão). E então, caso for um palíndromo, colocamos ele também.
Esse código roda em (Temos dp para calcular, e cada uma leva operações para ser calculada). Segue o código para melhor entendimento (Link)