Compare commits
3 Commits
18be861612
...
189f75019b
| Author | SHA1 | Date | |
|---|---|---|---|
| 189f75019b | |||
| 9c9bb62c23 | |||
| a4fc2530e3 |
BIN
analise-de-dados/arthur-dolival-analise-de-dados-tutorial.pdf
Normal file
BIN
analise-de-dados/arthur-dolival-analise-de-dados-tutorial.pdf
Normal file
Binary file not shown.
@@ -0,0 +1,46 @@
|
|||||||
|
\documentclass[10pt]{article}
|
||||||
|
\usepackage[utf8]{inputenc}
|
||||||
|
\usepackage{amsmath,amsthm,amssymb}
|
||||||
|
\usepackage{fullpage}
|
||||||
|
\usepackage{url}
|
||||||
|
\pagenumbering{gobble}
|
||||||
|
\usepackage{hyperref}
|
||||||
|
\usepackage{graphicx}
|
||||||
|
\input{statement/preamble.tex}
|
||||||
|
|
||||||
|
\title{ Tutorial: Análise de Dados}
|
||||||
|
\author{Leetcode 1223}
|
||||||
|
\date{}
|
||||||
|
\begin{document}
|
||||||
|
\maketitle
|
||||||
|
O problema pode ser resolvido por meio de uma abordagem de \textbf{programação dinâmica}, onde calculamos o número de sequências válidas de lançamentos de dados até cada posição, levando em consideração qual foi a última face sorteada e quantas vezes ela apareceu consecutivamente.
|
||||||
|
|
||||||
|
A principal restrição é que cada face \( i \) (\(1 \le i \le 6\)) só pode aparecer no máximo \( d_i \) vezes seguidas. Assim, ao adicionar um novo lançamento à sequência, precisamos garantir que essa condição nunca seja violada.
|
||||||
|
|
||||||
|
Definimos a seguinte estrutura de DP:
|
||||||
|
|
||||||
|
\[
|
||||||
|
dp[i][j] = \text{número de sequências válidas de comprimento } i \text{ cuja última face lançada é } j
|
||||||
|
\]
|
||||||
|
|
||||||
|
Para lidar com o número de repetições consecutivas, expandimos a ideia considerando blocos consecutivos de uma mesma face.
|
||||||
|
Para cada face \( k \), podemos adicioná-la de \(1\) até \(d_k\) vezes, desde que a sequência anterior termine com uma face diferente de \(k\).
|
||||||
|
|
||||||
|
Assim, a função de transição é dada por:
|
||||||
|
\[
|
||||||
|
dp[i][k] = \sum_{j \ne k} \sum_{x = 1}^{\min(d_k, i)} dp[i - x][j]
|
||||||
|
\]
|
||||||
|
onde o termo \(dp[i - x][j]\) representa o número de sequências de comprimento \(i - x\) que terminam com uma face diferente de \(k\), às quais adicionamos \(x\) ocorrências consecutivas da face \(k\).
|
||||||
|
|
||||||
|
As condições iniciais são:
|
||||||
|
\[
|
||||||
|
dp[0][j] = 1, \quad \forall j \in \{1, 2, 3, 4, 5, 6\}
|
||||||
|
\]
|
||||||
|
representando a sequência vazia inicial, que serve como base para as transições.
|
||||||
|
|
||||||
|
A resposta final será a soma de todas as formas possíveis de terminar a sequência de comprimento \(n\):
|
||||||
|
\[
|
||||||
|
\sum_{j=1}^{6} dp[n][j] \bmod (10^9 + 7)
|
||||||
|
\]
|
||||||
|
|
||||||
|
A complexidade temporal dessa solução é \(O(n \times 6 \times \text{max}(d_i))\), pois para cada posição e cada face consideramos até \(d_i\) possíveis comprimentos de repetições.\end{document}
|
||||||
BIN
analise-de-dados/arthur-dolival-analise-de-dados.pdf
Normal file
BIN
analise-de-dados/arthur-dolival-analise-de-dados.pdf
Normal file
Binary file not shown.
54
analise-de-dados/arthur-dolival-analise-de-dados.tex
Normal file
54
analise-de-dados/arthur-dolival-analise-de-dados.tex
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
\documentclass{maratona}
|
||||||
|
|
||||||
|
\begin{document}
|
||||||
|
\begin{ProblemaAutor}{}{Análise de Dados}{1}{256}{Leetcode 1223}
|
||||||
|
|
||||||
|
É o seu primeiro dia no \textbf{Departamento de Controle de Qualidade}.
|
||||||
|
|
||||||
|
Você esperava analisar planilhas, gráficos e talvez alguns modelos estatísticos... mas o laboratório te surpreende.
|
||||||
|
|
||||||
|
Logo ao entrar, seu gerente te conduz até uma máquina barulhenta, repleta de cabos coloridos e um enorme botão vermelho no topo.
|
||||||
|
|
||||||
|
--- “Aqui nós fazemos \textbf{análise de dados}.”, ele diz, com um sorriso confiante.
|
||||||
|
|
||||||
|
Você concorda, achando que entendeu, até perceber que a máquina está literalmente lançando um dado de seis faces a cada segundo.
|
||||||
|
|
||||||
|
Sim, você vai analisar \textbf{dados de verdade}.
|
||||||
|
|
||||||
|
Mas há um problema: os dados do laboratório sofrem de \textit{fadiga de repetição}.
|
||||||
|
Se uma mesma face aparecer muitas vezes seguidas, o mecanismo emperra e a máquina trava, o que, segundo o manual, “não é recomendável”.
|
||||||
|
|
||||||
|
Cada face $i$ ($1 \le i \le 6$) possui um limite $d_i$: o número máximo de vezes que ela pode aparecer consecutivamente antes de causar uma falha.
|
||||||
|
|
||||||
|
Sua tarefa é determinar quantas sequências de lançamentos de comprimento $n$ podem ser geradas sem que a máquina quebre.
|
||||||
|
|
||||||
|
Como o número de sequências válidas pode ser gigantesco, o gerente exige que o resultado seja dado módulo $10^9 + 7$.
|
||||||
|
|
||||||
|
\Entrada
|
||||||
|
|
||||||
|
A entrada contém um inteiro \(n\) que representa o número de lançamentos do dado, onde \(1 \leq n \leq 5000\).
|
||||||
|
Em seguida, são dados seis inteiros \(d_1, d_2, d_3, d_4, d_5, d_6\), cada um representando o número máximo de vezes consecutivas que a face correspondente pode aparecer, com \(1 \leq d_i \leq 15\).
|
||||||
|
|
||||||
|
\Saida
|
||||||
|
|
||||||
|
A saída consiste em um único inteiro representando o número total de sequências válidas de lançamentos, considerando o resultado módulo \(10^9 + 7\).
|
||||||
|
|
||||||
|
\ExemploEntrada
|
||||||
|
|
||||||
|
\begin{Exemplo}
|
||||||
|
\texttt{2} & \texttt{34}\\
|
||||||
|
\texttt{1~1~2~2~2~3} & \\
|
||||||
|
\rowcolor{gray!20}\texttt{2} & \texttt{30}\\
|
||||||
|
\rowcolor{gray!20}\texttt{1~1~1~1~1~1} & \\
|
||||||
|
\end{Exemplo}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
\Notas
|
||||||
|
|
||||||
|
No primeiro caso de teste, \(n = 2\) e os valores \(d\) são \((1, 1, 2, 2, 2, 3)\).
|
||||||
|
As faces \(1\) e \(2\) não podem aparecer repetidas consecutivamente, enquanto as demais possuem limites mais altos, resultando em \(34\) sequências válidas.
|
||||||
|
Como há \(2\) lançamentos de dado e \(6\) faces, sem restrições haveria \(6 \times 6 = 36\) combinações possíveis.
|
||||||
|
Entretanto, as sequências \((1, 1)\) e \((2, 2)\) são inválidas devido às restrições de \(d_1 = 1\) e \(d_2 = 1\).
|
||||||
|
Logo, o total de combinações válidas é \(36 - 2 = 34\). \end{ProblemaAutor}
|
||||||
|
\end{document}
|
||||||
BIN
decode-ways/arthur-dolival-decode-ways-tutorial.pdf
Normal file
BIN
decode-ways/arthur-dolival-decode-ways-tutorial.pdf
Normal file
Binary file not shown.
74
decode-ways/arthur-dolival-decode-ways-tutorial.tex
Normal file
74
decode-ways/arthur-dolival-decode-ways-tutorial.tex
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
\documentclass[10pt]{article}
|
||||||
|
\usepackage[utf8]{inputenc}
|
||||||
|
\usepackage{amsmath,amsthm,amssymb}
|
||||||
|
\usepackage{fullpage}
|
||||||
|
\usepackage{url}
|
||||||
|
\pagenumbering{gobble}
|
||||||
|
\usepackage{hyperref}
|
||||||
|
\usepackage{graphicx}
|
||||||
|
\input{statement/preamble.tex}
|
||||||
|
|
||||||
|
\title{ Tutorial: Decodificando Mensagens}
|
||||||
|
\author{Leetcode 91}
|
||||||
|
\date{}
|
||||||
|
\begin{document}
|
||||||
|
\maketitle
|
||||||
|
O problema pode ser resolvido utilizando uma abordagem de \textbf{programação dinâmica}, na qual calculamos, passo a passo, o número de formas possíveis de decodificar a sequência até cada posição.
|
||||||
|
|
||||||
|
\subsection*{Modelagem}
|
||||||
|
|
||||||
|
Cada dígito (ou par de dígitos consecutivos) da sequência pode representar uma letra do alfabeto latino, seguindo a regra:
|
||||||
|
\[
|
||||||
|
1 \rightarrow A, \quad 2 \rightarrow B, \quad \ldots, \quad 26 \rightarrow Z
|
||||||
|
\]
|
||||||
|
Portanto, precisamos contar todas as maneiras válidas de interpretar a sequência numérica, considerando que apenas combinações entre $1$ e $26$ são válidas.
|
||||||
|
|
||||||
|
\subsection*{Definição da DP}
|
||||||
|
|
||||||
|
Definimos uma estrutura de DP com dois estados para cada posição $i$:
|
||||||
|
\begin{itemize}
|
||||||
|
\item $dp[i][0]$: número de mensagens possíveis terminando no caractere $i$ \textbf{quando o dígito atual não é concatenado} com o anterior;
|
||||||
|
\item $dp[i][1]$: número de mensagens possíveis terminando no caractere $i$ \textbf{quando o dígito atual é concatenado} com o anterior.
|
||||||
|
\end{itemize}
|
||||||
|
|
||||||
|
\subsection*{Função de Transição}
|
||||||
|
|
||||||
|
A função de transição é definida da seguinte forma:
|
||||||
|
\[
|
||||||
|
dp[i][0] =
|
||||||
|
\begin{cases}
|
||||||
|
dp[i - 1][0] + dp[i - 1][1], & \text{se } 1 \leq s[i] \leq 9 \\[6pt]
|
||||||
|
0, & \text{caso contrário}
|
||||||
|
\end{cases}
|
||||||
|
\]
|
||||||
|
|
||||||
|
\[
|
||||||
|
dp[i][1] =
|
||||||
|
\begin{cases}
|
||||||
|
dp[i - 2][0] + dp[i - 2][1], & \text{se } 10 \leq 10 \cdot s[i-1] + s[i] \leq 26 \\[6pt]
|
||||||
|
0, & \text{caso contrário}
|
||||||
|
\end{cases}
|
||||||
|
\]
|
||||||
|
|
||||||
|
\subsection*{Casos Base}
|
||||||
|
|
||||||
|
Os casos base são:
|
||||||
|
\[
|
||||||
|
dp[0][0] = 1, \quad dp[0][1] = 0, \quad dp[1][0] = 1, \quad dp[1][1] = 0
|
||||||
|
\]
|
||||||
|
Isso ocorre porque, antes de processar qualquer caractere, há exatamente uma maneira “vazia” de formar uma mensagem válida, e o primeiro dígito pode, no máximo, representar uma única letra isolada.
|
||||||
|
|
||||||
|
\subsection*{Resposta Final}
|
||||||
|
|
||||||
|
O total de formas possíveis de decodificar a sequência é dado por:
|
||||||
|
\[
|
||||||
|
dp[n][0] + dp[n][1]
|
||||||
|
\]
|
||||||
|
onde $n$ é o comprimento da sequência de entrada.
|
||||||
|
|
||||||
|
\subsection*{Complexidade}
|
||||||
|
|
||||||
|
\begin{itemize}
|
||||||
|
\item \textbf{Tempo:} $O(n)$, pois cada caractere é processado uma única vez;
|
||||||
|
\item \textbf{Espaço:} $O(n)$, podendo ser otimizado para $O(1)$ ao armazenar apenas os últimos dois estados.
|
||||||
|
\end{itemize}\end{document}
|
||||||
BIN
decode-ways/arthur-dolival-decode-ways.pdf
Normal file
BIN
decode-ways/arthur-dolival-decode-ways.pdf
Normal file
Binary file not shown.
39
decode-ways/arthur-dolival-decode-ways.tex
Normal file
39
decode-ways/arthur-dolival-decode-ways.tex
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
\documentclass{maratona}
|
||||||
|
|
||||||
|
\begin{document}
|
||||||
|
\begin{ProblemaAutor}{}{Decodificando Mensagens}{1}{256}{Leetcode 91}
|
||||||
|
|
||||||
|
O problema consiste em determinar o número de maneiras possíveis de decodificar uma sequência numérica, onde cada número ou par de números representa uma letra do alfabeto latino.
|
||||||
|
A correspondência segue a regra \( 1 \rightarrow A, 2 \rightarrow B, \ldots, 26 \rightarrow Z \).
|
||||||
|
Cada dígito ou combinação de dois dígitos consecutivos pode ser convertido em uma letra válida, desde que a sequência resultante obedeça às restrições de decodificação.
|
||||||
|
O objetivo é calcular o total de maneiras diferentes de decodificar a sequência numérica fornecida.
|
||||||
|
|
||||||
|
\Entrada
|
||||||
|
|
||||||
|
A entrada é composta por duas linhas.
|
||||||
|
A primeira linha contém um inteiro \( n \) (\( 1 \leq n \leq 100 \)), representando o tamanho da sequência numérica.
|
||||||
|
A segunda linha contém uma sequência de digitos de \( s \) de comprimento \( n \).
|
||||||
|
|
||||||
|
\Saida
|
||||||
|
|
||||||
|
A saída deve conter um único inteiro, representando o número total de maneiras possíveis de decodificar a sequência numérica \( s \) de acordo com o mapeamento \( 1 \rightarrow A, 2 \rightarrow B, \ldots, 26 \rightarrow Z \).
|
||||||
|
|
||||||
|
\ExemploEntrada
|
||||||
|
|
||||||
|
\begin{Exemplo}
|
||||||
|
\texttt{2} & \texttt{2}\\
|
||||||
|
\texttt{12} & \\
|
||||||
|
\rowcolor{gray!20}\texttt{3} & \texttt{3}\\
|
||||||
|
\rowcolor{gray!20}\texttt{226} & \\
|
||||||
|
\texttt{2} & \texttt{0}\\
|
||||||
|
\texttt{06} & \\
|
||||||
|
\end{Exemplo}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
\Notas
|
||||||
|
|
||||||
|
Para a sequência \( s = "12" \), existem duas decodificações possíveis: "AB" (1, 2) e "L" (12).
|
||||||
|
Para a sequência \( s = "226" \), há três decodificações possíveis: "BZ" (2, 26), "VF" (22, 6) e "BBF" (2, 2, 6).
|
||||||
|
Para a sequência \( s = "06" \), não há nenhuma forma válida de decodificação.\end{ProblemaAutor}
|
||||||
|
\end{document}
|
||||||
BIN
delete-and-earn/arthur-dolival-delete-and-earn-tutorial.pdf
Normal file
BIN
delete-and-earn/arthur-dolival-delete-and-earn-tutorial.pdf
Normal file
Binary file not shown.
66
delete-and-earn/arthur-dolival-delete-and-earn-tutorial.tex
Normal file
66
delete-and-earn/arthur-dolival-delete-and-earn-tutorial.tex
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
\documentclass[10pt]{article}
|
||||||
|
\usepackage[utf8]{inputenc}
|
||||||
|
\usepackage{amsmath,amsthm,amssymb}
|
||||||
|
\usepackage{fullpage}
|
||||||
|
\usepackage{url}
|
||||||
|
\pagenumbering{gobble}
|
||||||
|
\usepackage{hyperref}
|
||||||
|
\usepackage{graphicx}
|
||||||
|
\input{statement/preamble.tex}
|
||||||
|
|
||||||
|
\title{ Tutorial: Deletar e Ganhar}
|
||||||
|
\author{Leetcode 740}
|
||||||
|
\date{}
|
||||||
|
\begin{document}
|
||||||
|
\maketitle
|
||||||
|
O problema pode ser resolvido utilizando uma abordagem clássica de \textbf{programação dinâmica}.
|
||||||
|
A ideia central é que, ao escolher um número \( x \), ganhamos uma certa quantidade de pontos, mas perdemos a possibilidade de escolher os números \( x - 1 \) e \( x + 1 \), já que eles devem ser removidos da sequência.
|
||||||
|
|
||||||
|
\subsection*{Modelagem}
|
||||||
|
|
||||||
|
Primeiro, agrupamos os números iguais da sequência e calculamos o total de pontos que seria obtido caso escolhêssemos todos os elementos de valor \( i \):
|
||||||
|
\[
|
||||||
|
\text{points}[i] = (\text{quantidade de vezes que } i \text{ aparece}) \times i
|
||||||
|
\]
|
||||||
|
Assim, o problema passa a ser equivalente a escolher quais valores \( i \) maximizarão a soma total de pontos, respeitando a restrição de que, ao escolher \( i \), não podemos escolher \( i-1 \) nem \( i+1 \).
|
||||||
|
|
||||||
|
\subsection*{Definição da DP}
|
||||||
|
|
||||||
|
Definimos:
|
||||||
|
\[
|
||||||
|
dp[i] = \text{pontuação máxima possível utilizando apenas os números de } 1 \text{ até } i
|
||||||
|
\]
|
||||||
|
|
||||||
|
\subsection*{Função de Transição}
|
||||||
|
|
||||||
|
A cada passo, temos duas escolhas:
|
||||||
|
\begin{itemize}
|
||||||
|
\item \textbf{Não escolher} o número \( i \): nesse caso, o resultado é o mesmo que \( dp[i - 1] \);
|
||||||
|
\item \textbf{Escolher} o número \( i \): ganhamos \( \text{points}[i] \), mas não podemos utilizar \( i - 1 \), então somamos com \( dp[i - 2] \).
|
||||||
|
\end{itemize}
|
||||||
|
|
||||||
|
A função de transição é, portanto:
|
||||||
|
\[
|
||||||
|
dp[i] = \max(dp[i - 1], \, dp[i - 2] + \text{points}[i])
|
||||||
|
\]
|
||||||
|
|
||||||
|
\subsection*{Casos Base}
|
||||||
|
|
||||||
|
\[
|
||||||
|
dp[0] = 0, \quad dp[1] = \text{points}[1]
|
||||||
|
\]
|
||||||
|
|
||||||
|
\subsection*{Resposta Final}
|
||||||
|
|
||||||
|
A pontuação máxima possível é:
|
||||||
|
\[
|
||||||
|
dp[m]
|
||||||
|
\]
|
||||||
|
onde \( m \) é o maior valor presente na sequência original.
|
||||||
|
|
||||||
|
\subsection*{Complexidade}
|
||||||
|
|
||||||
|
\begin{itemize}
|
||||||
|
\item \textbf{Tempo:} \( O(m) \), onde \( m \) é o valor máximo na sequência;
|
||||||
|
\item \textbf{Espaço:} \( O(m) \), podendo ser otimizado para \( O(1) \) se armazenarmos apenas os dois últimos estados da DP.
|
||||||
|
\end{itemize}\end{document}
|
||||||
BIN
delete-and-earn/arthur-dolival-delete-and-earn.pdf
Normal file
BIN
delete-and-earn/arthur-dolival-delete-and-earn.pdf
Normal file
Binary file not shown.
42
delete-and-earn/arthur-dolival-delete-and-earn.tex
Normal file
42
delete-and-earn/arthur-dolival-delete-and-earn.tex
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
\documentclass{maratona}
|
||||||
|
|
||||||
|
\begin{document}
|
||||||
|
\begin{ProblemaAutor}{}{Deletar e Ganhar}{1}{256}{Leetcode 740}
|
||||||
|
|
||||||
|
O problema consiste em determinar a pontuação máxima que pode ser obtida ao realizar uma série de operações sobre uma sequência de números inteiros.
|
||||||
|
Em cada operação, é possível escolher um número \( x \) da sequência, somar \( x \) pontos ao total e, em seguida, remover \textbf{todos} os elementos iguais a \( x - 1 \) e \( x + 1 \) da sequência.
|
||||||
|
O processo pode ser repetido até que não existam mais números disponíveis.
|
||||||
|
O objetivo é maximizar a pontuação total obtida ao final das operações.
|
||||||
|
|
||||||
|
\Entrada
|
||||||
|
|
||||||
|
A entrada é composta por duas linhas.
|
||||||
|
A primeira linha contém um inteiro \( n \) (\( 1 \leq n \leq 20000 \)), representando o número de elementos da sequência.
|
||||||
|
A segunda linha contém \( n \) inteiros \( a_1, a_2, \ldots, a_n \) (\( 1 \leq a_i \leq 10000 \)), separados por espaços, correspondentes aos valores da sequência.
|
||||||
|
|
||||||
|
\Saida
|
||||||
|
|
||||||
|
A saída deve conter um único inteiro, representando a pontuação máxima possível obtida após realizar as operações descritas.
|
||||||
|
|
||||||
|
\ExemploEntrada
|
||||||
|
|
||||||
|
\begin{Exemplo}
|
||||||
|
\texttt{3} & \texttt{8}\\
|
||||||
|
\texttt{3~4~5} & \\
|
||||||
|
\rowcolor{gray!20}\texttt{6} & \texttt{9}\\
|
||||||
|
\rowcolor{gray!20}\texttt{2~2~3~3~3~4} & \\
|
||||||
|
\texttt{5} & \texttt{9}\\
|
||||||
|
\texttt{1~2~3~4~5} & \\
|
||||||
|
\end{Exemplo}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
\Notas
|
||||||
|
|
||||||
|
Para o primeiro caso de teste: \( (3, 4, 5) \), a melhor escolha é remover \( 3 \), o que concede 3 pontos e remove o número \( 4 \). Em seguida, remove-se o número \( 5 \), totalizando \( 3 + 5 = 8 \) pontos.
|
||||||
|
|
||||||
|
Para o segundo caso de teste: \( (2, 2, 3, 3, 3, 4) \), a melhor estratégia é escolher o número \( 3 \), que concede \( 3 \times 3 = 9 \) pontos, removendo todos os \( 2 \) e \( 4 \); o total máximo é \( 9 \).
|
||||||
|
|
||||||
|
Para o terceiro caso de teste: \( (1, 2, 3, 4, 5) \), a estratégia ótima é escolher \( 1 \), \( 3 \) e \( 5 \), obtendo \( 1 + 3 + 5 = 9 \) pontos no total.
|
||||||
|
\end{ProblemaAutor}
|
||||||
|
\end{document}
|
||||||
BIN
edit-distance/arthur-dolival-edit-distance-tutorial.pdf
Normal file
BIN
edit-distance/arthur-dolival-edit-distance-tutorial.pdf
Normal file
Binary file not shown.
53
edit-distance/arthur-dolival-edit-distance-tutorial.tex
Normal file
53
edit-distance/arthur-dolival-edit-distance-tutorial.tex
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
\documentclass[10pt]{article}
|
||||||
|
\usepackage[utf8]{inputenc}
|
||||||
|
\usepackage{amsmath,amsthm,amssymb}
|
||||||
|
\usepackage{fullpage}
|
||||||
|
\usepackage{url}
|
||||||
|
\pagenumbering{gobble}
|
||||||
|
\usepackage{hyperref}
|
||||||
|
\usepackage{graphicx}
|
||||||
|
\input{statement/preamble.tex}
|
||||||
|
|
||||||
|
\title{ Tutorial: Distância de Edição}
|
||||||
|
\author{}
|
||||||
|
\date{}
|
||||||
|
\begin{document}
|
||||||
|
\maketitle
|
||||||
|
\section{Solução do Problema}
|
||||||
|
|
||||||
|
O problema de encontrar o menor número de operações para transformar uma string em outra, classicamente conhecido como Distância de Edição (\textit{Edit Distance}), pode ser resolvido de forma eficiente por meio de \textbf{programação dinâmica}.
|
||||||
|
|
||||||
|
\subsection{Definição do Subproblema}
|
||||||
|
|
||||||
|
Sejam $w_1$ e $w_2$ as duas strings de tamanhos $N$ e $M$, respectivamente.
|
||||||
|
Definimos o nosso estado da programação dinâmica como:
|
||||||
|
|
||||||
|
$$dp[i][j] = \text{número mínimo de operações para transformar o sufixo } w_1[i \dots N-1] \text{ no sufixo } w_2[j \dots M-1].$$
|
||||||
|
|
||||||
|
Assim, $dp[0][0]$ representará a resposta final para as duas strings inteiras.
|
||||||
|
|
||||||
|
\subsection{Função de Transição}
|
||||||
|
|
||||||
|
Para determinar $dp[i][j]$, olhamos para os caracteres atuais $w_1[i]$ e $w_2[j]$ e tomamos uma decisão.
|
||||||
|
|
||||||
|
Se os caracteres forem iguais ($w_1[i] == w_2[j]$), não precisamos realizar nenhuma operação. Apenas avançamos na análise de ambas as strings:
|
||||||
|
|
||||||
|
$$dp[i][j] = dp[i+1][j+1]$$
|
||||||
|
|
||||||
|
Se os caracteres forem diferentes ($w_1[i] \neq w_2[j]$), temos três opções de edição. Avaliamos o resultado de aplicar cada uma delas e escolhemos a que produz o menor custo final. Cada operação tem um custo de $1$:
|
||||||
|
|
||||||
|
$$dp[i][j] = 1 + \min \begin{cases}
|
||||||
|
dp[i+1][j] & \text{(Remoção do caractere } w_1[i]\text{)} \\
|
||||||
|
dp[i+1][j+1] & \text{(Substituição de } w_1[i] \text{ por } w_2[j]\text{)} \\
|
||||||
|
dp[i][j+1] & \text{(Inserção do caractere } w_2[j] \text{ em } w_1\text{)}
|
||||||
|
\end{cases}$$
|
||||||
|
|
||||||
|
\subsection{Casos Base}
|
||||||
|
|
||||||
|
Os casos base ocorrem quando esgotamos os caracteres de uma das strings (ou seja, quando $i$ ou $j$ ultrapassam os limites):
|
||||||
|
|
||||||
|
Se consumirmos toda a string $w_1$ ($i \ge N$), mas ainda restarem caracteres em $w_2$, a única forma de igualá-las é \textbf{inserir} todos os $M - j$ caracteres restantes:
|
||||||
|
$$dp[N][j] = M - j$$
|
||||||
|
|
||||||
|
Da mesma forma, se consumirmos toda a string $w_2$ ($j \ge M$), mas ainda restarem caracteres em $w_1$, a única forma de igualá-las é \textbf{remover} todos os $N - i$ caracteres que sobraram:
|
||||||
|
$$dp[i][M] = N - i$$\end{document}
|
||||||
BIN
edit-distance/arthur-dolival-edit-distance.pdf
Normal file
BIN
edit-distance/arthur-dolival-edit-distance.pdf
Normal file
Binary file not shown.
43
edit-distance/arthur-dolival-edit-distance.tex
Normal file
43
edit-distance/arthur-dolival-edit-distance.tex
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
\documentclass{maratona}
|
||||||
|
|
||||||
|
\begin{document}
|
||||||
|
\begin{ProblemaAutor}{}{Distância de Edição}{1}{256}{}
|
||||||
|
|
||||||
|
O problema consiste em determinar o \textbf{menor número de operações} necessárias para transformar uma string em outra.
|
||||||
|
|
||||||
|
As operações permitidas são as seguintes:
|
||||||
|
|
||||||
|
\begin{itemize}
|
||||||
|
\item \textbf{Inserção}: inserir um caractere em qualquer posição;
|
||||||
|
\item \textbf{Remoção}: remover um caractere de qualquer posição;
|
||||||
|
\item \textbf{Substituição}: substituir um caractere por outro.
|
||||||
|
\end{itemize}
|
||||||
|
|
||||||
|
O objetivo é calcular o menor custo possível para converter completamente uma dada string inicial em uma string final, utilizando apenas essas operações.
|
||||||
|
|
||||||
|
\Entrada
|
||||||
|
|
||||||
|
A entrada consiste de duas linhas:
|
||||||
|
|
||||||
|
\begin{itemize}
|
||||||
|
\item A primeira linha contém dois inteiros \( n \) e \( m \) (\( 1 \leq n, m \leq 500 \)), representando os tamanhos das strings.
|
||||||
|
\item A segunda linha contém duas strings \( s_1 \) e \( s_2 \), ambas compostas apenas por letras minúsculas e com tamanhos exatos \( n \) e \( m \), respectivamente.
|
||||||
|
\end{itemize}
|
||||||
|
|
||||||
|
\Saida
|
||||||
|
|
||||||
|
Imprima um único inteiro representando o \textbf{menor número de operações} necessárias para transformar \( s_1 \) em \( s_2 \).
|
||||||
|
|
||||||
|
\ExemploEntrada
|
||||||
|
|
||||||
|
\begin{Exemplo}
|
||||||
|
\texttt{7~7} & \texttt{3}\\
|
||||||
|
\texttt{estouro~calouro} & \\
|
||||||
|
\rowcolor{gray!20}\texttt{11~8} & \texttt{7}\\
|
||||||
|
\rowcolor{gray!20}\texttt{aniquilacao~intencao} & \\
|
||||||
|
\end{Exemplo}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
\end{ProblemaAutor}
|
||||||
|
\end{document}
|
||||||
BIN
estouro/arthur-dolival-estouro-tutorial.pdf
Normal file
BIN
estouro/arthur-dolival-estouro-tutorial.pdf
Normal file
Binary file not shown.
54
estouro/arthur-dolival-estouro-tutorial.tex
Normal file
54
estouro/arthur-dolival-estouro-tutorial.tex
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
\documentclass[10pt]{article}
|
||||||
|
\usepackage[utf8]{inputenc}
|
||||||
|
\usepackage{amsmath,amsthm,amssymb}
|
||||||
|
\usepackage{fullpage}
|
||||||
|
\usepackage{url}
|
||||||
|
\pagenumbering{gobble}
|
||||||
|
\usepackage{hyperref}
|
||||||
|
\usepackage{graphicx}
|
||||||
|
\input{statement/preamble.tex}
|
||||||
|
|
||||||
|
\title{ Tutorial: Estouro}
|
||||||
|
\author{Leetcode 312}
|
||||||
|
\date{}
|
||||||
|
\begin{document}
|
||||||
|
\maketitle
|
||||||
|
\section{Solução do Problema}
|
||||||
|
|
||||||
|
O problema de maximizar a energia ao estourar balões pode ser resolvido de forma eficiente por meio de \textbf{programação dinâmica em intervalos}. A grande sacada para modelar este problema é pensar no processo de trás para frente: em vez de tentar adivinhar qual balão estourar primeiro, o que muda constantemente os vizinhos dos balões restantes, escolhemos qual será o \textbf{último balão} a ser estourado em um determinado subintervalo.
|
||||||
|
|
||||||
|
Para lidar com as bordas da fileira sem precisar de múltiplos \texttt{if}s, adicionamos balões virtuais com valor $1$ nas extremidades.
|
||||||
|
|
||||||
|
\subsection{Definição do Subproblema}
|
||||||
|
|
||||||
|
Seja a nossa fileira de balões original de tamanho $N$. Criamos um novo vetor $B$ de tamanho $N+2$, onde $B[0] = 1$, $B[N+1] = 1$, e as posições de $1$ a $N$ recebem os valores fornecidos.
|
||||||
|
|
||||||
|
Definimos o nosso estado da programação dinâmica como:
|
||||||
|
|
||||||
|
$$dp[i][j] = \text{a quantidade máxima de energia obtida ao estourar todos os balões no intervalo } [i, j].$$
|
||||||
|
|
||||||
|
Assim, $dp[1][N]$ representará a nossa resposta ótima, correspondente ao intervalo que engloba todos os balões reais.
|
||||||
|
|
||||||
|
\subsection{Função de Transição}
|
||||||
|
|
||||||
|
Para calcular $dp[i][j]$, vamos iterar por um pivô $k$ (com $i \le k \le j$) que representa o \textbf{último balão} a ser estourado dentro desse subintervalo.
|
||||||
|
|
||||||
|
Como $k$ é o último a sobreviver entre $i$ e $j$, todos os outros balões internos já foram estourados. Consequentemente, no exato momento da explosão de $k$, seus vizinhos diretos garantidamente serão $B[i-1]$ e $B[j+1]$. A energia liberada por esse estopim final será $B[i-1] \times B[k] \times B[j+1]$.
|
||||||
|
|
||||||
|
O valor total do intervalo será a soma da energia desse balão $k$ com as energias máximas dos subproblemas que o antecederam na ordem cronológica de explosão: o intervalo à esquerda ($i$ até $k-1$) e o intervalo à direita ($k+1$ até $j$). Portanto:
|
||||||
|
|
||||||
|
$$dp[i][j] = \max_{i \le k \le j} \big( dp[i][k-1] + B[i-1] \cdot B[k] \cdot B[j+1] + dp[k+1][j] \big)$$
|
||||||
|
|
||||||
|
\subsection{Casos Base}
|
||||||
|
|
||||||
|
Os casos base da nossa recursão (ou inicialização da matriz) ocorrem para intervalos vazios, ou seja, quando o índice de início ultrapassa o índice de fim ($i > j$). Nesses casos, como não há balões para estourar, a energia liberada é naturalmante nula:
|
||||||
|
|
||||||
|
$$dp[i][j] = 0 \quad \text{para todo } i > j$$
|
||||||
|
|
||||||
|
Como a implementação iterativa inicializa a matriz completa com zeros, essa condição já é suprida por padrão.
|
||||||
|
|
||||||
|
\subsection{Recuperação da Decomposição (Ordem das explosões)}
|
||||||
|
|
||||||
|
Para além da energia máxima $dp[1][N]$, frequentemente queremos também a sequência de explosões que atinge esse valor. Para isso, mantemos uma matriz auxiliar \texttt{cut[i][j]} durante a computação, que armazena o índice $k$ responsável pelo maior ganho em $dp[i][j]$.
|
||||||
|
|
||||||
|
Após preencher $dp$ e \texttt{cut}, criamos uma função recursiva para reconstruir a resposta. Ao chamarmos a função para o intervalo $[1, N]$, descobrimos o pivô $k = \texttt{cut}[1][N]$. Sabemos que $k$ é o \textit{último} balão estourado. Em seguida, chamamos recursivamente para os subintervalos $[1, k-1]$ e $[k+1, N]$. Ao empilharmos esses balões, obtemos a sequência cronológica invertida; basta inverter a lista no final para obtermos a sequência exata das explosões.\end{document}
|
||||||
BIN
estouro/arthur-dolival-estouro.pdf
Normal file
BIN
estouro/arthur-dolival-estouro.pdf
Normal file
Binary file not shown.
50
estouro/arthur-dolival-estouro.tex
Normal file
50
estouro/arthur-dolival-estouro.tex
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
\documentclass{maratona}
|
||||||
|
|
||||||
|
\begin{document}
|
||||||
|
\begin{ProblemaAutor}{}{Estouro}{1}{256}{Leetcode 312}
|
||||||
|
|
||||||
|
No laboratório de experimentos caóticos da \textbf{Fábrica de Balões Numéricos}, um cientista excêntrico te entrega uma fileira de balões, cada um pintado com um número inteiro positivo.
|
||||||
|
|
||||||
|
A regra do experimento é simples, ou pelo menos parece: você deve estourar todos os balões.
|
||||||
|
Porém, o nível de energia liberado em cada explosão depende dos balões que ainda restam ao redor.
|
||||||
|
|
||||||
|
Ao estourar o balão $i$, o experimento libera uma quantidade de energia igual a
|
||||||
|
\texttt{valor\_do\_balão[i-1] * valor\_do\_balão[i] * valor\_do\_balão[i+1]}.
|
||||||
|
Se algum dos vizinhos ($i-1$ ou $i+1$) não existir, imagine que há um balão virtual com o número $1$ nas extremidades.
|
||||||
|
|
||||||
|
Cada explosão altera completamente o arranjo restante, tornando o resultado imprevisível, a ordem em que você estoura os balões é crucial.
|
||||||
|
|
||||||
|
Sua missão é descobrir a \textbf{máxima quantidade total de energia} que pode ser liberada, escolhendo com sabedoria a sequência das explosões.
|
||||||
|
|
||||||
|
\Entrada
|
||||||
|
|
||||||
|
A primeira linha contém um inteiro $n$ ($1 \leq n \leq 300$), o número de balões.
|
||||||
|
|
||||||
|
A segunda linha contém $n$ inteiros $b_1, b_2, \ldots, b_n$ ($0 \leq b_i \leq 100$),
|
||||||
|
onde $b_i$ representa o número pintado no $i$-ésimo balão.
|
||||||
|
|
||||||
|
\Saida
|
||||||
|
|
||||||
|
Imprima um único inteiro, a \textbf{quantidade máxima total de energia} que pode ser liberada
|
||||||
|
ao estourar todos os balões na melhor ordem possível.
|
||||||
|
|
||||||
|
\ExemploEntrada
|
||||||
|
|
||||||
|
\begin{Exemplo}
|
||||||
|
\texttt{4} & \texttt{167}\\
|
||||||
|
\texttt{3~1~5~8} & \\
|
||||||
|
\rowcolor{gray!20}\texttt{2} & \texttt{10}\\
|
||||||
|
\rowcolor{gray!20}\texttt{1~5} & \\
|
||||||
|
\end{Exemplo}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
\Notas
|
||||||
|
|
||||||
|
No primeiro exemplo, ao estourar os balões na ordem ótima, a sequência de energias liberadas é:
|
||||||
|
$3 \times 1 \times 5 + 3 \times 5 \times 8 + 1 \times 3 \times 8 + 1 \times 8 \times 1 = 167$.
|
||||||
|
Portanto, o total máximo de energia é $167$.
|
||||||
|
|
||||||
|
No segundo exemplo, independentemente da ordem escolhida, a energia total liberada é
|
||||||
|
$1 \times 1 \times 5 + 1 \times 5 \times 1 = 10$.\end{ProblemaAutor}
|
||||||
|
\end{document}
|
||||||
BIN
flowers/arthur-dolival-flowers-tutorial.pdf
Normal file
BIN
flowers/arthur-dolival-flowers-tutorial.pdf
Normal file
Binary file not shown.
49
flowers/arthur-dolival-flowers-tutorial.tex
Normal file
49
flowers/arthur-dolival-flowers-tutorial.tex
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
\documentclass[10pt]{article}
|
||||||
|
\usepackage[utf8]{inputenc}
|
||||||
|
\usepackage{amsmath,amsthm,amssymb}
|
||||||
|
\usepackage{fullpage}
|
||||||
|
\usepackage{url}
|
||||||
|
\pagenumbering{gobble}
|
||||||
|
\usepackage{hyperref}
|
||||||
|
\usepackage{graphicx}
|
||||||
|
\input{statement/preamble.tex}
|
||||||
|
|
||||||
|
\title{ Tutorial: O problema das Flores}
|
||||||
|
\author{}
|
||||||
|
\date{}
|
||||||
|
\begin{document}
|
||||||
|
\maketitle
|
||||||
|
O problema pode ser resolvido utilizando uma abordagem de \textbf{programação dinâmica}, onde calculamos o número de maneiras válidas de preencher o canteiro até cada posição, levando em conta a cor da última flor e o tamanho do bloco atual de flores consecutivas.
|
||||||
|
|
||||||
|
A restrição principal é que não podem existir mais do que \(m\) flores consecutivas da mesma cor. Isso significa que, ao adicionar uma nova flor, precisamos garantir que a sequência resultante ainda seja válida, ou seja, o número de flores consecutivas da mesma cor não ultrapasse o limite imposto.
|
||||||
|
|
||||||
|
Definimos a DP da seguinte forma:
|
||||||
|
|
||||||
|
\[
|
||||||
|
dp[i][c] = \text{número de maneiras válidas de formar um arranjo de comprimento } i \text{ cuja última flor tem cor } c
|
||||||
|
\]
|
||||||
|
onde \(c = 0\) representa a cor \texttt{V} (vermelha) e \(c = 1\) representa a cor \texttt{B} (branca).
|
||||||
|
|
||||||
|
Para calcular \(dp[i][c]\), consideramos todos os blocos possíveis de flores consecutivas da mesma cor que terminam na posição \(i\).
|
||||||
|
Ou seja, podemos ter adicionado 1, 2, ..., até \(m\) flores consecutivas da cor \(c\), desde que o arranjo anterior termine com a cor oposta.
|
||||||
|
|
||||||
|
A função de transição é dada por:
|
||||||
|
|
||||||
|
\[
|
||||||
|
dp[i][c] = \sum_{k=1}^{m} dp[i - k][1 - c]
|
||||||
|
\]
|
||||||
|
para todo \(i \ge k\), pois estamos adicionando um bloco de \(k\) flores da cor \(c\) sobre um arranjo válido de comprimento \(i - k\) que termina com a cor oposta.
|
||||||
|
|
||||||
|
As condições base são:
|
||||||
|
\[
|
||||||
|
dp[0][0] = dp[0][1] = 1
|
||||||
|
\]
|
||||||
|
representando o caso vazio, que conta como uma configuração válida inicial para permitir as transições.
|
||||||
|
|
||||||
|
O resultado final é a soma de todos os arranjos válidos que terminam em qualquer cor:
|
||||||
|
\[
|
||||||
|
\text{Resposta} = dp[n][0] + dp[n][1]
|
||||||
|
\]
|
||||||
|
|
||||||
|
Essa solução possui complexidade de tempo \(O(n \times m)\), já que para cada posição \(i\) consideramos até \(m\) comprimentos de blocos consecutivos possíveis.
|
||||||
|
O espaço necessário é \(O(n)\), podendo ser otimizado para \(O(m)\) se apenas os estados recentes forem mantidos.\end{document}
|
||||||
BIN
flowers/arthur-dolival-flowers.pdf
Normal file
BIN
flowers/arthur-dolival-flowers.pdf
Normal file
Binary file not shown.
41
flowers/arthur-dolival-flowers.tex
Normal file
41
flowers/arthur-dolival-flowers.tex
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
\documentclass{maratona}
|
||||||
|
|
||||||
|
\begin{document}
|
||||||
|
\begin{ProblemaAutor}{}{O problema das Flores}{1}{256}{}
|
||||||
|
|
||||||
|
O Jardineiro Bino é conhecido por seus canteiros de flores meticulosamente planejados. Este ano, ele decidiu criar um canteiro linear de comprimento \(n\). Para cada uma das \(n\) posições no canteiro, Bino plantará exatamente uma flor, que pode ser ou vermelha (V) ou branca (B).
|
||||||
|
|
||||||
|
Bino é um artista, e a estética é sua principal preocupação. Ele acredita que a beleza surge da variação, mas também da harmonia. Após muita deliberação, ele estabeleceu uma regra de ouro para seu jardim: \textbf{nunca devem existir mais do que \(m\) flores consecutivas da mesma cor}.
|
||||||
|
|
||||||
|
Por exemplo, se \(n=5\) e \(m=2\), uma sequência como \texttt{V V B V V} é perfeitamente válida. No entanto, uma sequência como \texttt{V B B B V} é \emph{inválida}, pois contém um bloco de 3 flores brancas (\texttt{B B B}), o que excede o limite \(m=2\). Da mesma forma, \texttt{V V V V B} também é inválida por conter 4 flores vermelhas consecutivas.
|
||||||
|
|
||||||
|
Bino está planejando o jardim e quer saber quantas opções de design ele realmente tem. Seu desafio é ajudar Bino a determinar o número total de arranjos distintos que ele pode criar para seu canteiro de comprimento \(n\), respeitando estritamente sua regra de monotonia (o limite de \(m\)).
|
||||||
|
|
||||||
|
\Entrada
|
||||||
|
|
||||||
|
A entrada contém dois inteiros separados por espaço, \(n\) e \(m\), onde \(n\) (\(1 \leq n \leq 10\,000\)) é o comprimento da sequência de flores e \(m\) (\(1 \leq m \leq 1\,000\)) é o número máximo permitido de flores iguais consecutivas.
|
||||||
|
|
||||||
|
\Saida
|
||||||
|
|
||||||
|
Imprima um único número inteiro: o número total de sequências de flores válidas de comprimento \(n\) que satisfazem a restrição de Bino.
|
||||||
|
|
||||||
|
Como este número pode ser extremamente grande, sua resposta deve ser calculada e impressa \textbf{módulo \(10^9 + 7\)}.
|
||||||
|
|
||||||
|
\ExemploEntrada
|
||||||
|
|
||||||
|
\begin{Exemplo}
|
||||||
|
\texttt{1~1} & \texttt{2}\\
|
||||||
|
\rowcolor{gray!20}\texttt{2~2} & \texttt{4}\\
|
||||||
|
\texttt{2~1} & \texttt{2}\\
|
||||||
|
\end{Exemplo}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
\Notas
|
||||||
|
|
||||||
|
Caso de teste 1: \(n=1, m=1\).
|
||||||
|
Para uma sequência de comprimento 1 existem duas opções: {vermelha} ou {branca}. Portanto, o número de sequências válidas é 2.
|
||||||
|
|
||||||
|
Caso de teste 2: \(n=2, m=2\).
|
||||||
|
Como \(m \ge 2\), não há restrição efetiva para \(n=2\) além de que cada posição pode ser vermelha ou branca. Assim todas as \(2^2 = 4\) sequências são válidas.\end{ProblemaAutor}
|
||||||
|
\end{document}
|
||||||
BIN
knapsack-zero-one/arthur-dolival-knapsack-zero-one-tutorial.pdf
Normal file
BIN
knapsack-zero-one/arthur-dolival-knapsack-zero-one-tutorial.pdf
Normal file
Binary file not shown.
@@ -0,0 +1,72 @@
|
|||||||
|
\documentclass[10pt]{article}
|
||||||
|
\usepackage[utf8]{inputenc}
|
||||||
|
\usepackage{amsmath,amsthm,amssymb}
|
||||||
|
\usepackage{fullpage}
|
||||||
|
\usepackage{url}
|
||||||
|
\pagenumbering{gobble}
|
||||||
|
\usepackage{hyperref}
|
||||||
|
\usepackage{graphicx}
|
||||||
|
\input{statement/preamble.tex}
|
||||||
|
|
||||||
|
\title{ Tutorial: Knapsack Problem}
|
||||||
|
\author{}
|
||||||
|
\date{}
|
||||||
|
\begin{document}
|
||||||
|
\maketitle
|
||||||
|
\section{Solução do Problema}
|
||||||
|
|
||||||
|
A solução do problema da mochila 0/1 pode ser abordada por meio de \textit{programação dinâmica}.
|
||||||
|
A ideia central é decompor o problema em subproblemas menores, de forma que a solução ótima total seja composta pelas soluções ótimas desses subproblemas.
|
||||||
|
|
||||||
|
\subsection{Definição do Subproblema}
|
||||||
|
|
||||||
|
Seja $dp[i][w]$ o valor máximo que pode ser obtido ao considerar os $i$ primeiros itens, com capacidade máxima da mochila igual a $w$.
|
||||||
|
|
||||||
|
\subsection{Função de Transição}
|
||||||
|
|
||||||
|
Para cada item $i$ (com peso $p_i$ e valor $v_i$), temos duas opções:
|
||||||
|
|
||||||
|
\begin{itemize}
|
||||||
|
\item Não incluir o item $i$: o valor máximo permanece igual ao do subproblema anterior, isto é, $dp[i-1][w]$.
|
||||||
|
\item Incluir o item $i$: caso o peso $p_i$ caiba na mochila ($p_i \leq w$), o valor máximo será o valor do item $v_i$ somado ao melhor valor possível com a capacidade restante, $dp[i-1][w - p_i]$.
|
||||||
|
\end{itemize}
|
||||||
|
|
||||||
|
Assim, a função de transição pode ser expressa como:
|
||||||
|
|
||||||
|
\[
|
||||||
|
dp[i][w] =
|
||||||
|
\begin{cases}
|
||||||
|
dp[i-1][w], & \text{se } p_i > w \\
|
||||||
|
\max(dp[i-1][w],\; dp[i-1][w - p_i] + v_i), & \text{caso contrário}
|
||||||
|
\end{cases}
|
||||||
|
\]
|
||||||
|
|
||||||
|
\subsection{Casos Base}
|
||||||
|
|
||||||
|
As condições iniciais são:
|
||||||
|
|
||||||
|
\[
|
||||||
|
dp[0][w] = 0, \quad \forall w \geq 0
|
||||||
|
\]
|
||||||
|
\[
|
||||||
|
dp[i][0] = 0, \quad \forall i \geq 0
|
||||||
|
\]
|
||||||
|
|
||||||
|
Esses casos representam que, com zero itens ou capacidade zero, o valor máximo obtido é zero.
|
||||||
|
|
||||||
|
\subsection{Implementação Dinâmica}
|
||||||
|
|
||||||
|
O algoritmo preenche uma tabela $dp$ de tamanho $(n+1) \times (W+1)$, onde $n$ é o número de itens e $W$ é a capacidade máxima da mochila.
|
||||||
|
Cada célula é calculada a partir das decisões descritas na função de transição.
|
||||||
|
|
||||||
|
\begin{verbatim}
|
||||||
|
for i in 1..n:
|
||||||
|
for w in 1..W:
|
||||||
|
if peso[i] <= w:
|
||||||
|
dp[i][w] = max(dp[i-1][w], dp[i-1][w - peso[i]] + valor[i])
|
||||||
|
else:
|
||||||
|
dp[i][w] = dp[i-1][w]
|
||||||
|
\end{verbatim}
|
||||||
|
|
||||||
|
O resultado final é dado por $dp[n][W]$, que representa o maior valor possível que pode ser obtido sem ultrapassar a capacidade da mochila.
|
||||||
|
\end{document}
|
||||||
BIN
knapsack-zero-one/arthur-dolival-knapsack-zero-one.pdf
Normal file
BIN
knapsack-zero-one/arthur-dolival-knapsack-zero-one.pdf
Normal file
Binary file not shown.
51
knapsack-zero-one/arthur-dolival-knapsack-zero-one.tex
Normal file
51
knapsack-zero-one/arthur-dolival-knapsack-zero-one.tex
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
\documentclass{maratona}
|
||||||
|
|
||||||
|
\begin{document}
|
||||||
|
\begin{ProblemaAutor}{}{Knapsack Problem}{1}{256}{}
|
||||||
|
|
||||||
|
O problema consiste em determinar o maior valor total que pode ser obtido ao selecionar um subconjunto de itens para colocar em uma mochila com capacidade limitada.
|
||||||
|
Cada item possui um peso e um valor associados, e a mochila só pode suportar um peso total máximo.
|
||||||
|
O objetivo é escolher um conjunto de itens de forma que a soma de seus pesos não ultrapasse a capacidade máxima da mochila e que a soma de seus valores seja a maior possível.
|
||||||
|
Cada item pode ser escolhido no máximo uma vez.
|
||||||
|
|
||||||
|
\Entrada
|
||||||
|
|
||||||
|
A entrada é composta por \( N + 1 \) linhas.
|
||||||
|
Na primeira linha, há dois inteiros \( N \) e \( W \) (\( 1 \leq N \leq 100 \), \( 1 \leq W \leq 10^5 \)), representando respectivamente o número de itens e a capacidade máxima da mochila.
|
||||||
|
Cada uma das próximas \( N \) linhas contém dois inteiros \( w_i \) e \( v_i \) (\( 1 \leq w_i \leq W \), \( 1 \leq v_i \leq 10^9 \)), representando respectivamente o peso e o valor do \( i \)-ésimo item.
|
||||||
|
|
||||||
|
\Saida
|
||||||
|
|
||||||
|
Imprima um único inteiro representando o valor total máximo que pode ser obtido sem exceder a capacidade da mochila.
|
||||||
|
|
||||||
|
\ExemploEntrada
|
||||||
|
|
||||||
|
\begin{Exemplo}
|
||||||
|
\texttt{3~8} & \texttt{90}\\
|
||||||
|
\texttt{3~30} & \\
|
||||||
|
\texttt{4~50} & \\
|
||||||
|
\texttt{5~60} & \\
|
||||||
|
\rowcolor{gray!20}\texttt{5~5} & \texttt{5}\\
|
||||||
|
\rowcolor{gray!20}\texttt{1~1} & \\
|
||||||
|
\rowcolor{gray!20}\texttt{1~1} & \\
|
||||||
|
\rowcolor{gray!20}\texttt{1~1} & \\
|
||||||
|
\rowcolor{gray!20}\texttt{1~1} & \\
|
||||||
|
\rowcolor{gray!20}\texttt{1~1} & \\
|
||||||
|
\texttt{6~15} & \texttt{17}\\
|
||||||
|
\texttt{6~5} & \\
|
||||||
|
\texttt{5~6} & \\
|
||||||
|
\texttt{6~4} & \\
|
||||||
|
\texttt{6~6} & \\
|
||||||
|
\texttt{3~5} & \\
|
||||||
|
\texttt{7~2} & \\
|
||||||
|
\end{Exemplo}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
\Notas
|
||||||
|
|
||||||
|
Para o conjunto de itens \( (w_i, v_i) = \{(3, 30), (4, 50), (5, 60)\} \) e capacidade \( W = 8 \), a melhor escolha é pegar os itens de peso 3 e 5, totalizando valor 90.
|
||||||
|
Para o conjunto de itens \( (1, 1), (1, 1), (1, 1), (1, 1), (1, 1) \) e capacidade \( W = 5 \), todos os itens podem ser colocados, resultando em valor total \( 5 \).
|
||||||
|
Para o conjunto \( (6, 5), (5, 6), (6, 4), (6, 6), (3, 5), (7, 2) \) e capacidade \( W = 15 \), a melhor combinação alcança valor máximo 17.
|
||||||
|
\end{ProblemaAutor}
|
||||||
|
\end{document}
|
||||||
Binary file not shown.
@@ -0,0 +1,114 @@
|
|||||||
|
\documentclass[10pt]{article}
|
||||||
|
\usepackage[utf8]{inputenc}
|
||||||
|
\usepackage{amsmath,amsthm,amssymb}
|
||||||
|
\usepackage{fullpage}
|
||||||
|
\usepackage{url}
|
||||||
|
\pagenumbering{gobble}
|
||||||
|
\usepackage{hyperref}
|
||||||
|
\usepackage{graphicx}
|
||||||
|
\input{statement/preamble.tex}
|
||||||
|
|
||||||
|
\title{ Tutorial: Maior Subsequência Comum}
|
||||||
|
\author{}
|
||||||
|
\date{}
|
||||||
|
\begin{document}
|
||||||
|
\maketitle
|
||||||
|
\section{Solução do Problema}
|
||||||
|
|
||||||
|
O problema da maior subsequência comum (\textit{Longest Common Subsequence}, LCS) pode ser resolvido por meio de \textit{programação dinâmica}.
|
||||||
|
A ideia central é decompor o problema em subproblemas menores, de forma que a solução ótima final seja construída a partir das soluções ótimas desses subproblemas.
|
||||||
|
|
||||||
|
\subsection{Definição do Subproblema}
|
||||||
|
|
||||||
|
Sejam duas strings \( s_1 \) e \( s_2 \), de tamanhos \( n \) e \( m \), respectivamente.
|
||||||
|
Definimos:
|
||||||
|
|
||||||
|
\[
|
||||||
|
dp[i][j] = \text{o comprimento da maior subsequência comum entre } s_1[1..i] \text{ e } s_2[1..j].
|
||||||
|
\]
|
||||||
|
|
||||||
|
Isto é, \( dp[i][j] \) representa a resposta do problema considerando apenas os primeiros \( i \) caracteres de \( s_1 \) e os primeiros \( j \) caracteres de \( s_2 \).
|
||||||
|
|
||||||
|
\subsection{Função de Transição}
|
||||||
|
|
||||||
|
Ao analisar um par de posições \( (i, j) \), temos duas possibilidades principais:
|
||||||
|
|
||||||
|
\begin{itemize}
|
||||||
|
\item Se os caracteres atuais são iguais, isto é, \( s_1[i] = s_2[j] \), então podemos estender uma subsequência comum encontrada anteriormente:
|
||||||
|
\[
|
||||||
|
dp[i][j] = dp[i-1][j-1] + 1.
|
||||||
|
\]
|
||||||
|
|
||||||
|
\item Caso contrário, não é possível usar ambos os caracteres ao mesmo tempo, então devemos escolher o melhor resultado entre ignorar um dos dois:
|
||||||
|
\[
|
||||||
|
dp[i][j] = \max(dp[i-1][j], \, dp[i][j-1]).
|
||||||
|
\]
|
||||||
|
\end{itemize}
|
||||||
|
|
||||||
|
Assim, a função de transição pode ser resumida como:
|
||||||
|
|
||||||
|
\[
|
||||||
|
dp[i][j] =
|
||||||
|
\begin{cases}
|
||||||
|
dp[i-1][j-1] + 1, & \text{se } s_1[i] = s_2[j] \\
|
||||||
|
\max(dp[i-1][j], \, dp[i][j-1]), & \text{caso contrário}
|
||||||
|
\end{cases}
|
||||||
|
\]
|
||||||
|
|
||||||
|
\subsection{Casos Base}
|
||||||
|
|
||||||
|
Os casos base seguem a lógica natural do problema:
|
||||||
|
|
||||||
|
\[
|
||||||
|
dp[0][j] = 0 \quad \forall j \ge 0
|
||||||
|
\]
|
||||||
|
\[
|
||||||
|
dp[i][0] = 0 \quad \forall i \ge 0
|
||||||
|
\]
|
||||||
|
|
||||||
|
Isto representa que, se uma das strings tiver tamanho zero, nenhuma subsequência comum pode ser formada.
|
||||||
|
|
||||||
|
\subsection{Recuperação da Subsequência Comum}
|
||||||
|
|
||||||
|
Após o preenchimento da matriz \( dp \), o valor \( dp[n][m] \) fornece o comprimento da maior subsequência comum entre \( s_1 \) e \( s_2 \).
|
||||||
|
No entanto, para obter também a subsequência em si, é necessário realizar um processo de \textit{backtracking} sobre a matriz.
|
||||||
|
|
||||||
|
A ideia consiste em iniciar a partir da posição \( (n, m) \) da matriz e caminhar em direção à origem.
|
||||||
|
Em cada passo:
|
||||||
|
|
||||||
|
\begin{itemize}
|
||||||
|
\item Se \( s_1[i] = s_2[j] \), então este caractere faz parte da LCS. Nesse caso, retrocedemos para \( (i-1, j-1) \).
|
||||||
|
\item Caso contrário, avançamos para o vizinho que contém o maior valor entre \( dp[i-1][j] \) e \( dp[i][j-1] \), pois esse vizinho indica o caminho que manteve o comprimento máximo da subsequência.
|
||||||
|
\end{itemize}
|
||||||
|
|
||||||
|
Como a subsequência é reconstruída de trás para frente, os caracteres encontrados devem ser adicionados no início da string resultante.
|
||||||
|
|
||||||
|
O algoritmo para recuperar uma subsequência comum de comprimento máximo é o seguinte:
|
||||||
|
|
||||||
|
\begin{verbatim}
|
||||||
|
int i = n; // ponteiro para s1
|
||||||
|
int j = m; // ponteiro para s2
|
||||||
|
string lcs = ""; // subsequência comum sendo reconstruída
|
||||||
|
|
||||||
|
// Enquanto ainda houver caracteres a considerar
|
||||||
|
while (i > 0 && j > 0) {
|
||||||
|
|
||||||
|
// Caso 1: os caracteres são iguais → fazem parte da LCS
|
||||||
|
if (s1[i - 1] == s2[j - 1]) {
|
||||||
|
lcs = s1[i - 1] + lcs; // adiciona no início da string
|
||||||
|
i--;
|
||||||
|
j--;
|
||||||
|
}
|
||||||
|
// Caso 2: se o valor de cima é maior, movemos para cima
|
||||||
|
else if (dp[i - 1][j] > dp[i][j - 1]) {
|
||||||
|
i--;
|
||||||
|
}
|
||||||
|
// Caso 3: caso contrário, movemos para a esquerda
|
||||||
|
else {
|
||||||
|
j--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
\end{verbatim}
|
||||||
|
|
||||||
|
Ao final desse processo, a string \texttt{lcs} conterá uma maior subsequência comum entre as duas strings.\end{document}
|
||||||
Binary file not shown.
@@ -0,0 +1,43 @@
|
|||||||
|
\documentclass{maratona}
|
||||||
|
|
||||||
|
\begin{document}
|
||||||
|
\begin{ProblemaAutor}{}{Maior Subsequência Comum}{1}{256}{}
|
||||||
|
|
||||||
|
O objetivo deste problema é determinar o comprimento da \textbf{maior subsequência comum} (Longest Common Subsequence - LCS) entre duas strings fornecidas.
|
||||||
|
Uma \textit{subsequência} é uma sequência que pode ser obtida a partir de uma string original removendo-se zero ou mais caracteres, sem alterar a ordem relativa dos caracteres restantes.
|
||||||
|
Dadas duas strings \( s_1 \) e \( s_2 \), deseja-se determinar \textbf{o comprimento da maior subsequência comum} e também \textbf{uma subsequência comum de comprimento máximo} presente em ambas.
|
||||||
|
|
||||||
|
\Entrada
|
||||||
|
|
||||||
|
A entrada é composta por duas linhas.
|
||||||
|
Na primeira linha, há dois inteiros \( n \) e \( m \) (\( 1 \leq n, m \leq 1000 \)), representando respectivamente os tamanhos das strings \( s_1 \) e \( s_2 \).
|
||||||
|
Na segunda linha, há duas strings \( s_1 \) e \( s_2 \), cada uma composta apenas por letras minúsculas do alfabeto, com tamanhos \( n \) e \( m \), respectivamente.
|
||||||
|
|
||||||
|
\Saida
|
||||||
|
|
||||||
|
A saída consiste em duas linhas.
|
||||||
|
Na primeira linha, deve ser impresso o comprimento da maior subsequência comum.
|
||||||
|
Na segunda linha, deve ser impressa uma subsequência comum de comprimento máximo.
|
||||||
|
|
||||||
|
\ExemploEntrada
|
||||||
|
|
||||||
|
\begin{Exemplo}
|
||||||
|
\texttt{5~3} & \texttt{3}\\
|
||||||
|
\texttt{abcde~ace} & \texttt{ace}\\
|
||||||
|
\rowcolor{gray!20}\texttt{3~3} & \texttt{3}\\
|
||||||
|
\rowcolor{gray!20}\texttt{abc~abc} & \texttt{abc}\\
|
||||||
|
\texttt{3~3} & \texttt{0}\\
|
||||||
|
\texttt{abc~hhh} & \texttt{}\\
|
||||||
|
\end{Exemplo}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
\Notas
|
||||||
|
|
||||||
|
Para as strings \( s_1 = abcde \) e \( s_2 = ace \), a maior subsequência comum é "ace", que possui tamanho 3.
|
||||||
|
|
||||||
|
Para \( s_1 = abc \) e \( s_2 = abc \), ambas as strings são idênticas, logo a maior subsequência comum é "abc", que possui tamanho 3.
|
||||||
|
|
||||||
|
Para \( s_1 = abc \) e \( s_2 = hhh \), não há caracteres em comum, e portanto a maior subsequência comum é a palavra vazia, que tem tamanho 0.
|
||||||
|
\end{ProblemaAutor}
|
||||||
|
\end{document}
|
||||||
Binary file not shown.
@@ -0,0 +1,59 @@
|
|||||||
|
\documentclass[10pt]{article}
|
||||||
|
\usepackage[utf8]{inputenc}
|
||||||
|
\usepackage{amsmath,amsthm,amssymb}
|
||||||
|
\usepackage{fullpage}
|
||||||
|
\usepackage{url}
|
||||||
|
\pagenumbering{gobble}
|
||||||
|
\usepackage{hyperref}
|
||||||
|
\usepackage{graphicx}
|
||||||
|
\input{statement/preamble.tex}
|
||||||
|
|
||||||
|
\title{ Tutorial: Maior subsequência Crescente II}
|
||||||
|
\author{}
|
||||||
|
\date{}
|
||||||
|
\begin{document}
|
||||||
|
\maketitle
|
||||||
|
\section{Solução do Problema}
|
||||||
|
|
||||||
|
O problema de encontrar a maior subsequência crescente (\textit{Longest Increasing Subsequence} - LIS) possui uma solução clássica em $O(N^2)$, mas quando $N$ é grande, podemos otimizá-la para \textbf{$O(N \log N)$} combinando \textbf{programação dinâmica com busca binária}. A grande sacada dessa otimização é mudar a perspectiva: em vez de guardar o tamanho da maior subsequência que termina em um índice, guardamos o \textbf{menor valor final} possível para uma subsequência de um determinado comprimento.
|
||||||
|
|
||||||
|
\subsection{Definição do Subproblema}
|
||||||
|
|
||||||
|
Seja $a$ o nosso vetor de números inteiros de tamanho $N$.
|
||||||
|
Definimos o nosso estado da programação dinâmica como:
|
||||||
|
|
||||||
|
$$d[l] = \text{o menor valor que encerra uma subsequência crescente de comprimento exato } l.$$
|
||||||
|
|
||||||
|
O vetor $d$ terá uma propriedade muito importante: ele estará sempre rigorosamente ordenado de forma crescente. A resposta final será o maior $l$ tal que $d[l] \neq \infty$.
|
||||||
|
|
||||||
|
\subsection{Função de Transição}
|
||||||
|
|
||||||
|
Para calcular $d[l]$, iteramos sobre cada elemento $a[i]$ da nossa sequência original. Como queremos que os elementos finais de cada comprimento sejam os menores possíveis, tentamos usar $a[i]$ para melhorar o nosso vetor $d$.
|
||||||
|
|
||||||
|
Como $d$ está ordenado, podemos usar \textbf{busca binária} (\texttt{upper\_bound} ou \texttt{lower\_bound}) para encontrar rapidamente a posição $l$ onde $a[i]$ deve ser inserido. Se $a[i]$ for maior que o final de uma subsequência de tamanho $l-1$ ($d[l-1] < a[i]$) e, ao mesmo tempo, puder substituir um final pior de tamanho $l$ ($a[i] < d[l]$), nós o atualizamos:
|
||||||
|
|
||||||
|
$$d[l] = a[i]$$
|
||||||
|
|
||||||
|
Isso significa que encontramos uma subsequência crescente de comprimento $l$ que termina em $a[i]$, e esse final é melhor (menor) do que o que tínhamos registrado anteriormente.
|
||||||
|
|
||||||
|
\subsection{Casos Base}
|
||||||
|
|
||||||
|
Para que a lógica de busca e as comparações iniciais funcionem sem estourar os limites, inicializamos o vetor $d$ de tamanho $N+1$ da seguinte forma:
|
||||||
|
|
||||||
|
$$d[0] = -\infty$$
|
||||||
|
$$d[l] = \infty \quad \text{para todo } 1 \le l \le N$$
|
||||||
|
|
||||||
|
Isso representa que uma subsequência de tamanho $0$ termina em um valor infinitamente pequeno, enquanto os outros comprimentos ainda não foram alcançados.
|
||||||
|
|
||||||
|
\subsection{Recuperação da Decomposição (Elementos da subsequência)}
|
||||||
|
|
||||||
|
Para recuperar os elementos exatos da LIS nesta abordagem otimizada, o vetor $d$ sozinho não basta (pois ele pode conter uma mistura de elementos de diferentes subsequências válidas ao longo do tempo). Precisamos de duas estruturas de rastreamento:
|
||||||
|
\begin{itemize}
|
||||||
|
\item $pos[l]$: armazena o \textbf{índice original} do elemento que atualmente ocupa $d[l]$.
|
||||||
|
\item $p[i]$: armazena o predecessor do elemento de índice $i$, assim como na versão $O(N^2)$.
|
||||||
|
\end{itemize}
|
||||||
|
|
||||||
|
Durante a transição, sempre que atualizamos $d[l] = a[i]$, nós também registramos que esse elemento se encontra no índice $i$ original fazendo $pos[l] = i$.
|
||||||
|
Ao mesmo tempo, sabemos que o elemento imediatamente anterior a ele na subsequência é o elemento que termina o comprimento $l-1$. Logo, conectamos o predecessor: $p[i] = pos[l-1]$.
|
||||||
|
|
||||||
|
Ao final de todas as iterações, sabemos que \texttt{ans} é o comprimento máximo alcançado. O índice do último elemento dessa subsequência estará em $cur = pos[\texttt{ans}]$. A partir desse $cur$, reconstruímos a sequência retrocedendo $cur = p[cur]$ até atingir $-1$, e por fim invertemos a lista para exibi-la na ordem correta.\end{document}
|
||||||
Binary file not shown.
@@ -0,0 +1,42 @@
|
|||||||
|
\documentclass{maratona}
|
||||||
|
|
||||||
|
\begin{document}
|
||||||
|
\begin{ProblemaAutor}{}{Maior subsequência Crescente II}{1}{256}{}
|
||||||
|
|
||||||
|
O problema consiste em determinar a maior subsequência crescente de uma sequência de números inteiros.
|
||||||
|
Uma subsequência é formada ao remover zero ou mais elementos da sequência original, sem alterar a ordem relativa dos elementos restantes.
|
||||||
|
A subsequência procurada deve conter pelo menos um elemento, e seus valores devem estar em ordem estritamente crescente, isto é, para todos os índices válidos \( i \) e \( j \) pertencentes à subsequência, se \( i < j \) então \( a_i < a_j \).
|
||||||
|
O objetivo é identificar essa subsequência de tamanho máximo e apresentar tanto o seu comprimento quanto os próprios elementos.
|
||||||
|
|
||||||
|
\Entrada
|
||||||
|
|
||||||
|
A entrada é composta por duas linhas.
|
||||||
|
A primeira linha contém um inteiro \( N \) (\( 1 \leq N \leq 10^5 \)), representando o número de elementos da sequência.
|
||||||
|
A segunda linha contém \( N \) inteiros \( a_1, a_2, \ldots, a_N \) (\( -10^4 \leq a_i \leq 10^4 \)), separados por espaços, correspondentes aos elementos da sequência.
|
||||||
|
|
||||||
|
\Saida
|
||||||
|
|
||||||
|
A saída deve conter duas linhas.
|
||||||
|
A primeira linha deve conter um único inteiro representando o tamanho \( L \) da maior subsequência crescente.
|
||||||
|
A segunda linha deve conter \( L \) inteiros \( b_1, b_2, \ldots, b_L \), correspondentes aos elementos dessa subsequência, na mesma ordem em que aparecem na sequência original, separados por um espaço.
|
||||||
|
|
||||||
|
\ExemploEntrada
|
||||||
|
|
||||||
|
\begin{Exemplo}
|
||||||
|
\texttt{5} & \texttt{5}\\
|
||||||
|
\texttt{1~2~3~4~5} & \texttt{1~2~3~4~5}\\
|
||||||
|
\rowcolor{gray!20}\texttt{4} & \texttt{3}\\
|
||||||
|
\rowcolor{gray!20}\texttt{2~3~-1~4} & \texttt{2~3~4}\\
|
||||||
|
\texttt{1} & \texttt{1}\\
|
||||||
|
\texttt{0} & \texttt{0}\\
|
||||||
|
\end{Exemplo}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
\Notas
|
||||||
|
|
||||||
|
Para a sequência \( (1, 2, 3, 4, 5) \), toda a sequência já é estritamente crescente, portanto o tamanho da subsequência é \( L = 5 \) e ela contém os mesmos elementos.
|
||||||
|
Para a sequência \( (2, 3, -1, 4) \), uma das maiores subsequências crescentes possíveis é \( (2, 3, 4) \), com tamanho \( L = 3 \).
|
||||||
|
Para a sequência \( (0) \), há apenas um elemento, então a maior subsequência crescente é o próprio número \( 0 \), com tamanho \( L = 1 \).
|
||||||
|
\end{ProblemaAutor}
|
||||||
|
\end{document}
|
||||||
Binary file not shown.
@@ -0,0 +1,50 @@
|
|||||||
|
\documentclass[10pt]{article}
|
||||||
|
\usepackage[utf8]{inputenc}
|
||||||
|
\usepackage{amsmath,amsthm,amssymb}
|
||||||
|
\usepackage{fullpage}
|
||||||
|
\usepackage{url}
|
||||||
|
\pagenumbering{gobble}
|
||||||
|
\usepackage{hyperref}
|
||||||
|
\usepackage{graphicx}
|
||||||
|
\input{statement/preamble.tex}
|
||||||
|
|
||||||
|
\title{ Tutorial: Maior subsequência Crescente}
|
||||||
|
\author{}
|
||||||
|
\date{}
|
||||||
|
\begin{document}
|
||||||
|
\maketitle
|
||||||
|
\section{Solução do Problema}
|
||||||
|
|
||||||
|
O problema de encontrar a maior subsequência crescente (\textit{Longest Increasing Subsequence} - LIS) é um clássico que pode ser resolvido de forma eficiente por meio de \textbf{programação dinâmica}. A ideia central é focar no final da subsequência: para cada elemento da sequência original, calculamos qual é a maior subsequência crescente que termina exatamente nele.
|
||||||
|
|
||||||
|
\subsection{Definição do Subproblema}
|
||||||
|
|
||||||
|
Seja $a$ o nosso vetor de números inteiros com $N$ elementos, indexado de $0$ a $N-1$.
|
||||||
|
Definimos o nosso estado da programação dinâmica como:
|
||||||
|
|
||||||
|
$$d[i] = \text{o comprimento da maior subsequência crescente que termina obrigatoriamente no índice } i.$$
|
||||||
|
|
||||||
|
A resposta final para o tamanho da maior subsequência não será necessariamente $d[N-1]$, mas sim o maior valor alcançado em todo o vetor $d$, ou seja, $\max(d[i])$ para $0 \le i < N$.
|
||||||
|
|
||||||
|
\subsection{Função de Transição}
|
||||||
|
|
||||||
|
Para determinar o valor de $d[i]$, precisamos olhar para todos os elementos anteriores à posição $i$, ou seja, um índice $j$ tal que $0 \le j < i$.
|
||||||
|
|
||||||
|
Se encontrarmos um elemento anterior que seja estritamente menor que o elemento atual ($a[j] < a[i]$), isso significa que podemos estender a subsequência que terminava em $j$ anexando o elemento $a[i]$ ao final dela. O novo comprimento seria $d[j] + 1$.
|
||||||
|
Avaliamos todos os possíveis índices $j$ válidos e mantemos o que gera o maior comprimento:
|
||||||
|
|
||||||
|
$$d[i] = \max_{\substack{0 \le j < i \\ a[j] < a[i]}} \big( d[j] + 1 \big)$$
|
||||||
|
|
||||||
|
\subsection{Casos Base}
|
||||||
|
|
||||||
|
O caso base é bastante intuitivo: na pior das hipóteses, qualquer elemento isolado forma, por si só, uma subsequência válida de comprimento $1$. Portanto, a nossa inicialização padrão para todos os estados é:
|
||||||
|
|
||||||
|
$$d[i] = 1 \quad \text{para todo } 0 \le i < N$$
|
||||||
|
|
||||||
|
\subsection{Recuperação da Decomposição (Elementos da subsequência)}
|
||||||
|
|
||||||
|
Como o problema exige a impressão dos elementos que formam a subsequência, precisamos reconstruir o caminho ótimo. Para isso, utilizamos um vetor auxiliar $p[i]$ (de \textit{parent} ou predecessor), inicializado com $-1$.
|
||||||
|
|
||||||
|
Durante a transição, sempre que atualizamos $d[i]$ com um valor maior proveniente de um $d[j] + 1$, registramos o índice de origem definindo $p[i] = j$.
|
||||||
|
|
||||||
|
Após calcularmos todo o vetor $d$, localizamos o índice \texttt{pos} que contém o valor máximo absoluto de $d$. A partir de \texttt{pos}, recuperamos os elementos da subsequência percorrendo o caminho reverso: adicionamos $a[\texttt{pos}]$ à nossa lista de resposta e saltamos para o predecessor atualizando $\texttt{pos} = p[\texttt{pos}]$. Repetimos o processo até que $\texttt{pos}$ seja $-1$. Como resgatamos os elementos do final para o começo, basta inverter a lista resultante para apresentar a subsequência na ordem crescente original.\end{document}
|
||||||
Binary file not shown.
@@ -0,0 +1,42 @@
|
|||||||
|
\documentclass{maratona}
|
||||||
|
|
||||||
|
\begin{document}
|
||||||
|
\begin{ProblemaAutor}{}{Maior subsequência Crescente}{1}{256}{}
|
||||||
|
|
||||||
|
O problema consiste em determinar a maior subsequência crescente de uma sequência de números inteiros.
|
||||||
|
Uma subsequência é formada ao remover zero ou mais elementos da sequência original, sem alterar a ordem relativa dos elementos restantes.
|
||||||
|
A subsequência procurada deve conter pelo menos um elemento, e seus valores devem estar em ordem estritamente crescente, isto é, para todos os índices válidos \( i \) e \( j \) pertencentes à subsequência, se \( i < j \) então \( a_i < a_j \).
|
||||||
|
O objetivo é identificar essa subsequência de tamanho máximo e apresentar tanto o seu comprimento quanto os próprios elementos.
|
||||||
|
|
||||||
|
\Entrada
|
||||||
|
|
||||||
|
A entrada é composta por duas linhas.
|
||||||
|
A primeira linha contém um inteiro \( N \) (\( 1 \leq N \leq 1000 \)), representando o número de elementos da sequência.
|
||||||
|
A segunda linha contém \( N \) inteiros \( a_1, a_2, \ldots, a_N \) (\( -10^4 \leq a_i \leq 10^4 \)), separados por espaços, correspondentes aos elementos da sequência.
|
||||||
|
|
||||||
|
\Saida
|
||||||
|
|
||||||
|
A saída deve conter duas linhas.
|
||||||
|
A primeira linha deve conter um único inteiro representando o tamanho \( L \) da maior subsequência crescente.
|
||||||
|
A segunda linha deve conter \( L \) inteiros \( b_1, b_2, \ldots, b_L \), correspondentes aos elementos dessa subsequência, na mesma ordem em que aparecem na sequência original, separados por um espaço.
|
||||||
|
|
||||||
|
\ExemploEntrada
|
||||||
|
|
||||||
|
\begin{Exemplo}
|
||||||
|
\texttt{5} & \texttt{5}\\
|
||||||
|
\texttt{1~2~3~4~5} & \texttt{1~2~3~4~5}\\
|
||||||
|
\rowcolor{gray!20}\texttt{4} & \texttt{3}\\
|
||||||
|
\rowcolor{gray!20}\texttt{2~3~-1~4} & \texttt{2~3~4}\\
|
||||||
|
\texttt{1} & \texttt{1}\\
|
||||||
|
\texttt{0} & \texttt{0}\\
|
||||||
|
\end{Exemplo}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
\Notas
|
||||||
|
|
||||||
|
Para a sequência \( (1, 2, 3, 4, 5) \), toda a sequência já é estritamente crescente, portanto o tamanho da subsequência é \( L = 5 \) e ela contém os mesmos elementos.
|
||||||
|
Para a sequência \( (2, 3, -1, 4) \), uma das maiores subsequências crescentes possíveis é \( (2, 3, 4) \), com tamanho \( L = 3 \).
|
||||||
|
Para a sequência \( (0) \), há apenas um elemento, então a maior subsequência crescente é o próprio número \( 0 \), com tamanho \( L = 1 \).
|
||||||
|
\end{ProblemaAutor}
|
||||||
|
\end{document}
|
||||||
Binary file not shown.
@@ -0,0 +1,49 @@
|
|||||||
|
\documentclass[10pt]{article}
|
||||||
|
\usepackage[utf8]{inputenc}
|
||||||
|
\usepackage{amsmath,amsthm,amssymb}
|
||||||
|
\usepackage{fullpage}
|
||||||
|
\usepackage{url}
|
||||||
|
\pagenumbering{gobble}
|
||||||
|
\usepackage{hyperref}
|
||||||
|
\usepackage{graphicx}
|
||||||
|
\input{statement/preamble.tex}
|
||||||
|
|
||||||
|
\title{ Tutorial: Maior Subsequência Palindrômica}
|
||||||
|
\author{}
|
||||||
|
\date{}
|
||||||
|
\begin{document}
|
||||||
|
\maketitle
|
||||||
|
\section{Solução do Problema}
|
||||||
|
|
||||||
|
O problema de encontrar a Maior Subsequência Palindrômica (\textit{Longest Palindromic Subsequence} - LPS) pode ser resolvido de forma elegante utilizando \textbf{programação dinâmica em intervalos}. A ideia é analisar o problema de fora para dentro: comparamos os caracteres nas extremidades de uma substring e decidimos se eles farão parte do nosso palíndromo ou se devemos encolher o nosso intervalo de busca.
|
||||||
|
|
||||||
|
\subsection{Definição do Subproblema}
|
||||||
|
|
||||||
|
Seja $S$ a nossa string original de tamanho $N$, indexada de $0$ a $N-1$.
|
||||||
|
Definimos o nosso estado da programação dinâmica como:
|
||||||
|
|
||||||
|
$$dp[i][j] = \text{o comprimento da maior subsequência palindrômica dentro da substring } S[i \dots j].$$
|
||||||
|
|
||||||
|
Assim, a resposta para o comprimento máximo em toda a string será encontrada em $dp[0][N-1]$, que engloba o intervalo completo do primeiro ao último caractere.
|
||||||
|
|
||||||
|
\subsection{Função de Transição}
|
||||||
|
|
||||||
|
Para calcular $dp[i][j]$, olhamos para os caracteres nas pontas do intervalo atual: $S[i]$ e $S[j]$. Temos dois cenários possíveis:
|
||||||
|
|
||||||
|
1. \textbf{Os caracteres são iguais ($S[i] == S[j]$):} Eles podem formar as pontas de um palíndromo. Nesse caso, ganhamos $2$ de comprimento (um caractere de cada lado) e somamos ao melhor palíndromo que conseguimos formar no intervalo estritamente interno a eles.
|
||||||
|
$$dp[i][j] = dp[i+1][j-1] + 2$$
|
||||||
|
|
||||||
|
2. \textbf{Os caracteres são diferentes ($S[i] \neq S[j]$):} Como eles são diferentes, não podem formar as pontas do mesmo palíndromo simultaneamente. Precisamos descartar um dos lados e ver qual escolha nos dá o melhor resultado. Calculamos ignorando o caractere da esquerda (reduzindo para $i+1$) ou ignorando o da direita (reduzindo para $j-1$).
|
||||||
|
$$dp[i][j] = \max \big( dp[i+1][j], dp[i][j-1] \big)$$
|
||||||
|
|
||||||
|
\textit{Nota de implementação:} Para garantir que $dp[i+1][j-1]$ ou as outras dependências já estejam calculadas quando precisarmos delas, os laços devem processar os intervalos do menor para o maior, ou preenchendo o $i$ de trás para frente (de $N-1$ até $0$) e o $j$ de frente para trás (de $i+1$ até $N-1$).
|
||||||
|
|
||||||
|
\subsection{Casos Base}
|
||||||
|
|
||||||
|
Os casos base ocorrem para intervalos de tamanho 1 e intervalos inválidos (tamanho 0 ou negativo):
|
||||||
|
|
||||||
|
Todo caractere isolado é, por definição, um palíndromo de comprimento 1. Portanto, a diagonal principal da nossa matriz de estados recebe $1$:
|
||||||
|
$$dp[i][i] = 1 \quad \text{para todo } 0 \le i < N$$
|
||||||
|
|
||||||
|
Para intervalos onde o início ultrapassa o fim (o que pode ocorrer durante a transição de $dp[i+1][j-1]$ quando $j = i+1$), o comprimento é zero:
|
||||||
|
$$dp[i][j] = 0 \quad \text{para todo } i > j$$\end{document}
|
||||||
Binary file not shown.
@@ -0,0 +1,39 @@
|
|||||||
|
\documentclass{maratona}
|
||||||
|
|
||||||
|
\begin{document}
|
||||||
|
\begin{ProblemaAutor}{}{Maior Subsequência Palindrômica}{1}{256}{}
|
||||||
|
|
||||||
|
O problema consiste em determinar a maior subsequência palindrômica de uma sequência de caracteres.
|
||||||
|
Uma subsequência é formada ao remover zero ou mais elementos da sequência original, sem alterar a ordem relativa dos elementos restantes.
|
||||||
|
A subsequência procurada deve ser um palíndromo, ou seja, deve ser idêntica quando lida de frente para trás ou de trás para frente.
|
||||||
|
O objetivo é identificar essa subsequência de tamanho máximo e apresentar tanto o seu comprimento quanto os próprios elementos.
|
||||||
|
|
||||||
|
\Entrada
|
||||||
|
|
||||||
|
A entrada é composta por duas linhas.
|
||||||
|
A primeira linha contém um inteiro \( n \) (\( 1 \leq n \leq 1000 \)), representando o número de caracteres da sequência.
|
||||||
|
A segunda linha contém uma string \( s \) de comprimento \( n \), composta por letras minúsculas do alfabeto.
|
||||||
|
|
||||||
|
\Saida
|
||||||
|
|
||||||
|
A saída é composta por uma linha, um único inteiro, que representa representando o tamanho \( L \) da maior subsequência palindrômica.
|
||||||
|
|
||||||
|
\ExemploEntrada
|
||||||
|
|
||||||
|
\begin{Exemplo}
|
||||||
|
\texttt{5} & \texttt{4}\\
|
||||||
|
\texttt{bbbab} & \\
|
||||||
|
\rowcolor{gray!20}\texttt{4} & \texttt{2}\\
|
||||||
|
\rowcolor{gray!20}\texttt{cbbd} & \\
|
||||||
|
\texttt{1} & \texttt{1}\\
|
||||||
|
\texttt{a} & \\
|
||||||
|
\end{Exemplo}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
\Notas
|
||||||
|
|
||||||
|
Para a sequência "bbbab", o tamanho da maior subsequência palindrômica é \( L = 4 \) e uma possível sequência é "bbbb".
|
||||||
|
Para a sequência "cbbd", a maior subsequência palindrômica é "bb", com tamanho \( L = 2 \).
|
||||||
|
Para a sequência "a", há apenas um elemento, então a maior subsequência palindrômica é o próprio caractere "a", com tamanho \( L = 1 \).\end{ProblemaAutor}
|
||||||
|
\end{document}
|
||||||
Binary file not shown.
@@ -0,0 +1,62 @@
|
|||||||
|
\documentclass[10pt]{article}
|
||||||
|
\usepackage[utf8]{inputenc}
|
||||||
|
\usepackage{amsmath,amsthm,amssymb}
|
||||||
|
\usepackage{fullpage}
|
||||||
|
\usepackage{url}
|
||||||
|
\pagenumbering{gobble}
|
||||||
|
\usepackage{hyperref}
|
||||||
|
\usepackage{graphicx}
|
||||||
|
\input{statement/preamble.tex}
|
||||||
|
|
||||||
|
\title{ Tutorial: Maximum Subarray Sum}
|
||||||
|
\author{}
|
||||||
|
\date{}
|
||||||
|
\begin{document}
|
||||||
|
\maketitle
|
||||||
|
O problema pode ser resolvido eficientemente utilizando uma abordagem de \textbf{programação dinâmica}, comumente conhecida como \textbf{Algoritmo de Kadane}. A ideia central é calcular, para cada posição $i$ da sequência, a maior soma de uma subsequência contínua que termina exatamente naquela posição.
|
||||||
|
|
||||||
|
\subsection*{Modelagem}
|
||||||
|
|
||||||
|
Dada uma sequência de entrada $A$ de tamanho $n$ (com índices de $0$ a $n-1$), queremos encontrar a maior soma possível $\sum_{k=i}^{j} A[k]$ para quaisquer índices $0 \leq i \leq j < n$.
|
||||||
|
|
||||||
|
O algoritmo de Kadane resolve isso de forma linear, mantendo o controle da melhor subsequência encontrada até o momento.
|
||||||
|
|
||||||
|
\subsection*{Definição da DP}
|
||||||
|
|
||||||
|
Definimos $dp[i]$ como o valor da \textbf{maior soma de uma subsequência contínua que termina no índice $i$}.
|
||||||
|
|
||||||
|
\subsection*{Função de Transição}
|
||||||
|
|
||||||
|
Para calcular o valor de $dp[i]$, temos duas escolhas:
|
||||||
|
|
||||||
|
A subsequência máxima que termina em $i$ é formada \textbf{apenas pelo elemento $A[i]$}. Isso ocorre se a soma da subsequência anterior ($dp[i-1]$) for negativa, pois estendê-la apenas diminuiria o valor.
|
||||||
|
|
||||||
|
A subsequência máxima que termina em $i$ é uma \textbf{extensão da subsequência máxima que terminava em $i-1$}, adicionando $A[i]$. A soma seria $dp[i-1] + A[i]$.
|
||||||
|
|
||||||
|
Selecionamos a maior dessas duas opções. Portanto, a função de transição é:
|
||||||
|
|
||||||
|
$$dp[i] = \max(A[i], \quad dp[i-1] + A[i])$$
|
||||||
|
|
||||||
|
\subsection*{Casos Base}
|
||||||
|
|
||||||
|
A primeira subsequência possível (que termina no índice $0$) deve obrigatoriamente conter $A[0]$.
|
||||||
|
O caso base é:
|
||||||
|
|
||||||
|
$$dp[0] = A[0]$$
|
||||||
|
|
||||||
|
\subsection*{Resposta Final}
|
||||||
|
|
||||||
|
É importante notar que $dp[n-1]$ é apenas a maior soma terminando na última posição, o que não é necessariamente a resposta final do problema.
|
||||||
|
|
||||||
|
A subsequência de soma máxima pode terminar em qualquer índice $i$. Portanto, a resposta final é o \textbf{valor máximo encontrado em todo o array $dp$}.
|
||||||
|
|
||||||
|
$$ \max_{0 \leq i < n} (dp[i])$$
|
||||||
|
|
||||||
|
\subsection*{Complexidade}
|
||||||
|
|
||||||
|
\begin{itemize}
|
||||||
|
\item \textbf{Tempo:} $O(n)$, pois percorremos a sequência de entrada uma única vez para preencher o array $dp$. Encontrar o máximo do array $dp$ também leva $O(n)$, o que pode ser feito simultaneamente.
|
||||||
|
\item \textbf{Espaço:} $O(n)$ para armazenar o array $dp$.
|
||||||
|
\end{itemize}
|
||||||
|
|
||||||
|
\textbf{Otimização de Espaço:} Note que o cálculo de $dp[i]$ depende apenas de $dp[i-1]$. Podemos otimizar o espaço para $O(1)$ mantendo apenas duas variáveis: uma para a "soma máxima terminando aqui" (equivalente a $dp[i-1]$) e outra para a "soma máxima global" (a resposta final).\end{document}
|
||||||
BIN
maximum-subarray-sum/arthur-dolival-maximum-subarray-sum.pdf
Normal file
BIN
maximum-subarray-sum/arthur-dolival-maximum-subarray-sum.pdf
Normal file
Binary file not shown.
39
maximum-subarray-sum/arthur-dolival-maximum-subarray-sum.tex
Normal file
39
maximum-subarray-sum/arthur-dolival-maximum-subarray-sum.tex
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
\documentclass{maratona}
|
||||||
|
|
||||||
|
\begin{document}
|
||||||
|
\begin{ProblemaAutor}{}{Maximum Subarray Sum}{1}{256}{}
|
||||||
|
|
||||||
|
O problema consiste em determinar a maior soma possível de uma subsequência contínua de uma sequência de números inteiros.
|
||||||
|
Uma subsequência contínua é formada por um ou mais elementos consecutivos da sequência original, sem interrupções.
|
||||||
|
A subsequência escolhida deve conter pelo menos um elemento, e o objetivo é encontrar aquela cuja soma dos elementos seja máxima.
|
||||||
|
|
||||||
|
\Entrada
|
||||||
|
|
||||||
|
A entrada é composta por duas linhas.
|
||||||
|
A primeira linha contém um inteiro \( n \) (\( 1 \leq n \leq 10^5 \)), representando o número de elementos da sequência.
|
||||||
|
A segunda linha contém \( n \) inteiros \( a_1, a_2, \ldots, a_n \) (\( -10^4 \leq a_i \leq 10^4 \)), separados por espaços, correspondentes aos elementos da sequência.
|
||||||
|
|
||||||
|
\Saida
|
||||||
|
|
||||||
|
A saída deve conter um único inteiro, representando a maior soma possível obtida por uma subsequência contínua não vazia da sequência fornecida.
|
||||||
|
|
||||||
|
\ExemploEntrada
|
||||||
|
|
||||||
|
\begin{Exemplo}
|
||||||
|
\texttt{5} & \texttt{15}\\
|
||||||
|
\texttt{1~2~3~4~5} & \\
|
||||||
|
\rowcolor{gray!20}\texttt{4} & \texttt{8}\\
|
||||||
|
\rowcolor{gray!20}\texttt{2~3~-1~4} & \\
|
||||||
|
\texttt{1} & \texttt{0}\\
|
||||||
|
\texttt{0} & \\
|
||||||
|
\end{Exemplo}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
\Notas
|
||||||
|
|
||||||
|
Para a sequência \( (1, 2, 3, 4, 5) \), toda a sequência é positiva, portanto a maior soma é \( 15 \).
|
||||||
|
Para a sequência \( (2, 3, -1, 4) \), a subsequência com maior soma é \( (2, 3, -1, 4) \), totalizando \( 8 \).
|
||||||
|
Para a sequência \( (0) \), há apenas um elemento, logo a maior soma é \( 0 \).
|
||||||
|
\end{ProblemaAutor}
|
||||||
|
\end{document}
|
||||||
BIN
min-sum-path-2d/arthur-dolival-min-sum-path-2d-tutorial.pdf
Normal file
BIN
min-sum-path-2d/arthur-dolival-min-sum-path-2d-tutorial.pdf
Normal file
Binary file not shown.
82
min-sum-path-2d/arthur-dolival-min-sum-path-2d-tutorial.tex
Normal file
82
min-sum-path-2d/arthur-dolival-min-sum-path-2d-tutorial.tex
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
\documentclass[10pt]{article}
|
||||||
|
\usepackage[utf8]{inputenc}
|
||||||
|
\usepackage{amsmath,amsthm,amssymb}
|
||||||
|
\usepackage{fullpage}
|
||||||
|
\usepackage{url}
|
||||||
|
\pagenumbering{gobble}
|
||||||
|
\usepackage{hyperref}
|
||||||
|
\usepackage{graphicx}
|
||||||
|
\input{statement/preamble.tex}
|
||||||
|
|
||||||
|
\title{ Tutorial: Caminho de Menor Soma}
|
||||||
|
\author{}
|
||||||
|
\date{}
|
||||||
|
\begin{document}
|
||||||
|
\maketitle
|
||||||
|
\section{Solução do Problema}
|
||||||
|
|
||||||
|
O problema consiste em encontrar o \textbf{menor custo} necessário para percorrer uma grade (\textit{matriz}) de inteiros positivos.
|
||||||
|
A grade possui \( n \) linhas e \( m \) colunas, e cada célula contém um número positivo que representa o custo de passar por ela.
|
||||||
|
|
||||||
|
O objetivo é sair da célula \textbf{superior esquerda} da grade e chegar à célula \textbf{inferior direita}, movendo-se apenas para a \textbf{direita} ou para \textbf{baixo}.
|
||||||
|
A soma dos valores das células visitadas deve ser a menor possível.
|
||||||
|
|
||||||
|
Este problema pode ser resolvido de forma eficiente utilizando \textbf{programação dinâmica}.
|
||||||
|
|
||||||
|
\subsection{Definição do Subproblema}
|
||||||
|
|
||||||
|
Seja uma matriz de custos \( C \) de tamanho \( n \times m \). Definimos:
|
||||||
|
|
||||||
|
\[
|
||||||
|
dp[i][j] = \text{o menor custo para chegar à célula } (i,j) \text{ a partir de } (0,0).
|
||||||
|
\]
|
||||||
|
|
||||||
|
Ou seja, \( dp[i][j] \) representa o custo mínimo para alcançar exatamente a posição \( (i, j) \).
|
||||||
|
|
||||||
|
\subsection{Função de Transição}
|
||||||
|
|
||||||
|
Como só é possível mover-se para a \textbf{direita} ou para \textbf{baixo}, a célula \( (i,j) \) só pode ser alcançada a partir de:
|
||||||
|
|
||||||
|
\begin{itemize}
|
||||||
|
\item \( (i-1, j) \): movimento vindo de \textbf{cima};
|
||||||
|
\item \( (i, j-1) \): movimento vindo da \textbf{esquerda}.
|
||||||
|
\end{itemize}
|
||||||
|
|
||||||
|
Assim, o custo mínimo para chegar a \( (i,j) \) é dado por:
|
||||||
|
|
||||||
|
\[
|
||||||
|
dp[i][j] = C[i][j] + \min(dp[i-1][j],\ dp[i][j-1]).
|
||||||
|
\]
|
||||||
|
|
||||||
|
\subsection{Casos Base}
|
||||||
|
|
||||||
|
\begin{itemize}
|
||||||
|
\item Primeira célula:
|
||||||
|
\[
|
||||||
|
dp[0][0] = C[0][0]
|
||||||
|
\]
|
||||||
|
\item Primeira linha (somente movimentos para a direita):
|
||||||
|
\[
|
||||||
|
dp[0][j] = dp[0][j-1] + C[0][j]
|
||||||
|
\]
|
||||||
|
\item Primeira coluna (somente movimentos para baixo):
|
||||||
|
\[
|
||||||
|
dp[i][0] = dp[i-1][0] + C[i][0]
|
||||||
|
\]
|
||||||
|
\end{itemize}
|
||||||
|
|
||||||
|
\subsection{Construção da Tabela}
|
||||||
|
|
||||||
|
Após inicializar os casos base, preenchermos o restante da matriz \( dp \) utilizando:
|
||||||
|
|
||||||
|
\[
|
||||||
|
dp[i][j] = C[i][j] + \min(dp[i-1][j],\ dp[i][j-1]).
|
||||||
|
\]
|
||||||
|
|
||||||
|
Ao término do processo, o valor da última posição:
|
||||||
|
|
||||||
|
\[
|
||||||
|
dp[n-1][m-1]
|
||||||
|
\]
|
||||||
|
|
||||||
|
representa o \textbf{menor custo possível} para ir da célula inicial até a célula final.\end{document}
|
||||||
BIN
min-sum-path-2d/arthur-dolival-min-sum-path-2d.pdf
Normal file
BIN
min-sum-path-2d/arthur-dolival-min-sum-path-2d.pdf
Normal file
Binary file not shown.
38
min-sum-path-2d/arthur-dolival-min-sum-path-2d.tex
Normal file
38
min-sum-path-2d/arthur-dolival-min-sum-path-2d.tex
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
\documentclass{maratona}
|
||||||
|
|
||||||
|
\begin{document}
|
||||||
|
\begin{ProblemaAutor}{}{Caminho de Menor Soma}{1}{256}{}
|
||||||
|
|
||||||
|
O problema consiste em encontrar o menor custo possível para percorrer uma grade de inteiros positivos.
|
||||||
|
A grade possui \( n \) linhas e \( m \) colunas, e cada célula contém um valor inteiro positivo que representa o custo de passar por ela.
|
||||||
|
|
||||||
|
O objetivo é sair da célula superior esquerda da grade e chegar à célula inferior direita, movendo-se apenas para a direita ou para baixo.
|
||||||
|
A soma dos valores das células visitadas deve ser a menor possível.
|
||||||
|
|
||||||
|
\Entrada
|
||||||
|
|
||||||
|
A entrada é composta por \( n + 1 \) linhas. Na primeira linha, há dois inteiros \( n \) e \( m \) (\( 1 \leq n, m \leq 1000 \)), representando respectivamente o número de linhas e de colunas da grade.
|
||||||
|
Cada uma das próximas \( n \) linhas contém \( m \) inteiros \( a_{i,j} \) (\( 1 \leq a_{i,j} \leq 100 \)), representando o custo da célula na linha \( i \) e coluna \( j \).
|
||||||
|
|
||||||
|
\Saida
|
||||||
|
|
||||||
|
Imprima um único inteiro representando o menor custo total para ir da célula superior esquerda até a célula inferior direita, movendo-se apenas para a direita ou para baixo.
|
||||||
|
|
||||||
|
\ExemploEntrada
|
||||||
|
|
||||||
|
\begin{Exemplo}
|
||||||
|
\texttt{1~1} & \texttt{5}\\
|
||||||
|
\texttt{5} & \\
|
||||||
|
\rowcolor{gray!20}\texttt{2~2} & \texttt{7}\\
|
||||||
|
\rowcolor{gray!20}\texttt{1~3} & \\
|
||||||
|
\rowcolor{gray!20}\texttt{2~4} & \\
|
||||||
|
\texttt{3~3} & \texttt{21}\\
|
||||||
|
\texttt{1~2~3} & \\
|
||||||
|
\texttt{4~5~6} & \\
|
||||||
|
\texttt{7~8~9} & \\
|
||||||
|
\end{Exemplo}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
\end{ProblemaAutor}
|
||||||
|
\end{document}
|
||||||
@@ -45,7 +45,7 @@
|
|||||||
"main-ac": "ac.cpp",
|
"main-ac": "ac.cpp",
|
||||||
"alternative-ac": ["ac_constant_time_heap.c"],
|
"alternative-ac": ["ac_constant_time_heap.c"],
|
||||||
"wrong-answer": [],
|
"wrong-answer": [],
|
||||||
"time-limit": [],
|
"time-limit": ["tle.cpp", "tle2.cpp","tle3.cpp"],
|
||||||
"time-limit-or-ac": [],
|
"time-limit-or-ac": [],
|
||||||
"time-limit-or-memory-limit": [],
|
"time-limit-or-memory-limit": [],
|
||||||
"memory-limit": [],
|
"memory-limit": [],
|
||||||
|
|||||||
Binary file not shown.
@@ -35,6 +35,7 @@ Para cada caso de teste na entrada, seu programa deve produzir uma linha de saí
|
|||||||
Se não houver como o Sr. Rã chegar até a casa da Sra. Sapo, seu programa deve imprimir 'impossible', sem as aspas simples.
|
Se não houver como o Sr. Rã chegar até a casa da Sra. Sapo, seu programa deve imprimir 'impossible', sem as aspas simples.
|
||||||
|
|
||||||
\ExemploEntrada
|
\ExemploEntrada
|
||||||
|
|
||||||
\begin{Exemplo}
|
\begin{Exemplo}
|
||||||
\texttt{4~4} & \texttt{14}\\
|
\texttt{4~4} & \texttt{14}\\
|
||||||
\texttt{1~1~4~2} & \texttt{impossible}\\
|
\texttt{1~1~4~2} & \texttt{impossible}\\
|
||||||
|
|||||||
184
ra-preguicosa/src/ac_constant_time_heap.c
Normal file
184
ra-preguicosa/src/ac_constant_time_heap.c
Normal file
@@ -0,0 +1,184 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#define INF 0x3f3f3f3f
|
||||||
|
#define MAX 150000
|
||||||
|
typedef struct node_t{
|
||||||
|
int i;
|
||||||
|
int j;
|
||||||
|
int c;
|
||||||
|
}node_t;
|
||||||
|
|
||||||
|
/*pantano*/
|
||||||
|
char mesh[1001][1001];
|
||||||
|
int custo[1002][1002];
|
||||||
|
char calculado[1002][1002];
|
||||||
|
int inserido[1002][1002];
|
||||||
|
node_t filas[8][MAX];
|
||||||
|
int contadoresInicio[8];
|
||||||
|
int contadoresFim[8];
|
||||||
|
int C,R;
|
||||||
|
int Cf,Rf,Ct,Rt;
|
||||||
|
int C1,R1,C2,R2;
|
||||||
|
int W;
|
||||||
|
int currentFila;
|
||||||
|
|
||||||
|
/*Escova bit*/
|
||||||
|
inline int get_int(){
|
||||||
|
int ch, i;
|
||||||
|
while (((ch = getchar()) == ' ') || (ch == '\n'));
|
||||||
|
for (i = 0; ch >= '0' && ch <= '9'; ch = getchar() )
|
||||||
|
i = 10 * i + (ch - '0');
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void insere(node_t no,int custo){
|
||||||
|
int balde = custo%8;
|
||||||
|
inserido[no.i][no.j] = balde;
|
||||||
|
filas[balde][contadoresFim[balde]++] = no;
|
||||||
|
}
|
||||||
|
|
||||||
|
int retira(node_t* aux){
|
||||||
|
int start = currentFila;
|
||||||
|
while(contadoresInicio[currentFila]==contadoresFim[currentFila]){
|
||||||
|
currentFila++;
|
||||||
|
if(currentFila==8) currentFila = 0;
|
||||||
|
if(currentFila==start) return(0);
|
||||||
|
}
|
||||||
|
*aux = filas[currentFila][contadoresInicio[currentFila]++];
|
||||||
|
return(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*Funcao q testa os limites do tabuleiro e outras coisas
|
||||||
|
*do Dijkstra
|
||||||
|
*/
|
||||||
|
int testa(node_t current,int i,int j,int c){
|
||||||
|
|
||||||
|
int custoAtual = custo[current.i][current.j];
|
||||||
|
node_t temp;
|
||||||
|
if(!(i<=R && i>=1 && j<=C && j>=1)){
|
||||||
|
return(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(calculado[i][j]){
|
||||||
|
return(1);
|
||||||
|
}
|
||||||
|
if(mesh[i][j]==0){
|
||||||
|
/*relaxamento*/
|
||||||
|
if(custoAtual+c < custo[i][j]){
|
||||||
|
custo[i][j] = custoAtual+c;
|
||||||
|
/*insere normal*/
|
||||||
|
temp.i = i;
|
||||||
|
temp.j = j;
|
||||||
|
temp.c = custo[i][j];
|
||||||
|
insere(temp,(custo[i][j]));
|
||||||
|
}
|
||||||
|
return(1);
|
||||||
|
}
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int getFila(){
|
||||||
|
int i;
|
||||||
|
for(i=0;i<8;i++){
|
||||||
|
if(contadoresInicio[i]<contadoresFim[i]){
|
||||||
|
return(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return(8);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(void){
|
||||||
|
int i,j,k;
|
||||||
|
node_t aux;
|
||||||
|
node_t sapo;
|
||||||
|
while(C=get_int(),R=get_int(),C||R){
|
||||||
|
memset(mesh,0,sizeof(char)*1001*1001);
|
||||||
|
memset(custo,0x3f,sizeof(int)*1002*1002);
|
||||||
|
//~ memset(calculado,0,sizeof(char)*1002*1002);
|
||||||
|
//~ memset(inserido,-1,sizeof(int)*1002*1002);/*nenhum nó foi inserido ainda*/
|
||||||
|
memset(contadoresInicio,0,sizeof(contadoresInicio));
|
||||||
|
memset(contadoresFim,0,sizeof(contadoresFim));
|
||||||
|
Cf = get_int();
|
||||||
|
Rf = get_int();
|
||||||
|
Ct = get_int();
|
||||||
|
Rt = get_int();
|
||||||
|
W = get_int();
|
||||||
|
for(k=0;k<W;k++){
|
||||||
|
C1 = get_int();
|
||||||
|
R1 = get_int();
|
||||||
|
C2 = get_int();
|
||||||
|
R2 = get_int();
|
||||||
|
for(i=R1;i<=R2;i++){
|
||||||
|
for(j=C1;j<=C2;j++){
|
||||||
|
mesh[i][j] = 1;/*alagado*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sapo.i = Rf; sapo.j = Cf;
|
||||||
|
custo[sapo.i][sapo.j] = 0;
|
||||||
|
insere(sapo,0);
|
||||||
|
currentFila = 0;
|
||||||
|
while(retira(&aux)){
|
||||||
|
if(aux.c > custo[aux.i][aux.j]) continue;
|
||||||
|
/*pega a frente de onda*/
|
||||||
|
//~ calculado[aux.i][aux.j] = 1;
|
||||||
|
|
||||||
|
/*Só faz sentido calcular o pulo mais distante
|
||||||
|
*de o pulo da frente tiver alagado
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*Superior*/
|
||||||
|
if(!testa(aux,aux.i+1,aux.j,2))
|
||||||
|
testa(aux,aux.i+2,aux.j,5);
|
||||||
|
|
||||||
|
/*Diagonais*/
|
||||||
|
if(!testa(aux,aux.i+1,aux.j-1,3)){
|
||||||
|
testa(aux,aux.i+2,aux.j-2,7);
|
||||||
|
testa(aux,aux.i+2,aux.j-1,6);
|
||||||
|
testa(aux,aux.i+1,aux.j-2,6);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*Diagonais*/
|
||||||
|
if(!testa(aux,aux.i+1,aux.j+1,3)){
|
||||||
|
testa(aux,aux.i+2,aux.j+2,7);
|
||||||
|
testa(aux,aux.i+2,aux.j+1,6);
|
||||||
|
testa(aux,aux.i+1,aux.j+2,6);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*parte lateral*/
|
||||||
|
|
||||||
|
if(!testa(aux,aux.i,aux.j-1,2))
|
||||||
|
testa(aux,aux.i,aux.j-2,5);
|
||||||
|
if(!testa(aux,aux.i,aux.j+1,2))
|
||||||
|
testa(aux,aux.i,aux.j+2,5);
|
||||||
|
|
||||||
|
/*parte de baixo*/
|
||||||
|
if(!testa(aux,aux.i-1,aux.j,2))
|
||||||
|
testa(aux,aux.i-2,aux.j,5);
|
||||||
|
/*Diagonais*/
|
||||||
|
if(!testa(aux,aux.i-1,aux.j-1,3)){
|
||||||
|
testa(aux,aux.i-2,aux.j-2,7);
|
||||||
|
testa(aux,aux.i-1,aux.j-2,6);
|
||||||
|
testa(aux,aux.i-2,aux.j-1,6);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*Diagonais*/
|
||||||
|
if(!testa(aux,aux.i-1,aux.j+1,3)){
|
||||||
|
testa(aux,aux.i-2,aux.j+2,7);
|
||||||
|
testa(aux,aux.i-2,aux.j+1,6);
|
||||||
|
testa(aux,aux.i-1,aux.j+2,6);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
if(custo[Rt][Ct]==INF){
|
||||||
|
printf("impossible\n");
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
printf("%d\n",custo[Rt][Ct]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
104
ra-preguicosa/src/tle.cpp
Normal file
104
ra-preguicosa/src/tle.cpp
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
#include <bits/stdc++.h>
|
||||||
|
|
||||||
|
#define endl '\n'
|
||||||
|
#define INF 0x3f3f3f3f
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
typedef pair<int, int> pii;
|
||||||
|
|
||||||
|
const int MAXN = 1e3 + 10;
|
||||||
|
|
||||||
|
int C, L, W;
|
||||||
|
int Cr, Lr, Cs, Ls;
|
||||||
|
const int COSTS[5][5] = {
|
||||||
|
{7, 6, 5, 6, 7},
|
||||||
|
{6, 3, 2, 3, 6},
|
||||||
|
{5, 2, 0, 2, 5},
|
||||||
|
{6, 3, 2, 3, 6},
|
||||||
|
{7, 6, 5, 6, 7},
|
||||||
|
};
|
||||||
|
bitset<MAXN> alagado[MAXN];
|
||||||
|
int g[MAXN][MAXN];
|
||||||
|
|
||||||
|
bool valid(int c, int l) {
|
||||||
|
return c > 0 && c <= C && l > 0 && l <= L && alagado[c][l] == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int h(int c, int l) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void solve()
|
||||||
|
{
|
||||||
|
for (int i = 1; i <= C; i++){
|
||||||
|
for (int j = 1; j <= L; j++){
|
||||||
|
g[i][j] = INF;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
priority_queue<
|
||||||
|
pair<int, pii>,
|
||||||
|
vector<pair<int, pii>>,
|
||||||
|
greater<>
|
||||||
|
> pq;
|
||||||
|
|
||||||
|
g[Cr][Lr] = 0;
|
||||||
|
pq.push({h(Cr, Lr), {Cr, Lr}});
|
||||||
|
|
||||||
|
while (!pq.empty()){
|
||||||
|
auto [curCost, curCoords] = pq.top();
|
||||||
|
pq.pop();
|
||||||
|
|
||||||
|
auto [c, l] = curCoords;
|
||||||
|
|
||||||
|
if (curCost != g[c][l] + h(c,l)) continue;
|
||||||
|
|
||||||
|
if (c == Cs && l == Ls){
|
||||||
|
cout << g[c][l] << endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = -2; i <= 2; i++){
|
||||||
|
for (int j = -2; j <= 2; j++){
|
||||||
|
int nc = c + i, nl = l + j;
|
||||||
|
if (!valid(nc, nl)) continue;
|
||||||
|
|
||||||
|
int cost = COSTS[i+2][j+2];
|
||||||
|
int newG = g[c][l] + cost;
|
||||||
|
|
||||||
|
if (newG < g[nc][nl]){
|
||||||
|
g[nc][nl] = newG;
|
||||||
|
pq.push({newG + h(nc, nl), {nc, nl}});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cout << "impossible" << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
ios::sync_with_stdio(false);
|
||||||
|
cin.tie(nullptr);
|
||||||
|
|
||||||
|
while (cin >> C >> L, C && L){
|
||||||
|
cin >> Cr >> Lr >> Cs >> Ls;
|
||||||
|
for (int i = 1; i <= C; i++){
|
||||||
|
for (int j = 1; j <= L; j++){
|
||||||
|
alagado[i][j]=0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cin >> W;
|
||||||
|
for (int i = 0; i < W; i++){
|
||||||
|
int C1, C2, L1, L2;
|
||||||
|
cin >> C1 >> L1 >> C2 >> L2;
|
||||||
|
for (int k = C1; k <= C2; k++)
|
||||||
|
for (int l = L1; l <= L2; l++)
|
||||||
|
alagado[k][l] = 1;
|
||||||
|
}
|
||||||
|
solve();
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
118
ra-preguicosa/src/tle2.cpp
Normal file
118
ra-preguicosa/src/tle2.cpp
Normal file
@@ -0,0 +1,118 @@
|
|||||||
|
#include <bits/stdc++.h>
|
||||||
|
|
||||||
|
#define endl '\n'
|
||||||
|
#define INF 0x3f3f3f3f
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
typedef pair<int, int> pii;
|
||||||
|
|
||||||
|
inline int get_int(){
|
||||||
|
int ch, i;
|
||||||
|
while (((ch = getchar()) == ' ') || (ch == '\n'));
|
||||||
|
for (i = 0; ch >= '0' && ch <= '9'; ch = getchar() )
|
||||||
|
i = 10 * i + (ch - '0');
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
const int MAXN = 1e3 + 10;
|
||||||
|
|
||||||
|
int C, L, W;
|
||||||
|
int Cr, Lr, Cs, Ls;
|
||||||
|
const int COSTS[5][5] = {
|
||||||
|
{7, 6, 5, 6, 7},
|
||||||
|
{6, 3, 2, 3, 6},
|
||||||
|
{5, 2, 0, 2, 5},
|
||||||
|
{6, 3, 2, 3, 6},
|
||||||
|
{7, 6, 5, 6, 7},
|
||||||
|
};
|
||||||
|
bitset<MAXN> alagado[MAXN];
|
||||||
|
int g[MAXN][MAXN];
|
||||||
|
|
||||||
|
bool valid(int c, int l) {
|
||||||
|
return c > 0 && c <= C && l > 0 && l <= L && alagado[c][l] == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int h(int c, int l) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void solve()
|
||||||
|
{
|
||||||
|
for (int i = 1; i <= C; i++){
|
||||||
|
for (int j = 1; j <= L; j++){
|
||||||
|
g[i][j] = INF;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
priority_queue<
|
||||||
|
pair<int, pii>,
|
||||||
|
vector<pair<int, pii>>,
|
||||||
|
greater<>
|
||||||
|
> pq;
|
||||||
|
|
||||||
|
g[Cr][Lr] = 0;
|
||||||
|
pq.push({h(Cr, Lr), {Cr, Lr}});
|
||||||
|
|
||||||
|
while (!pq.empty()){
|
||||||
|
auto [curCost, curCoords] = pq.top();
|
||||||
|
pq.pop();
|
||||||
|
|
||||||
|
auto [c, l] = curCoords;
|
||||||
|
|
||||||
|
if (curCost != g[c][l] + h(c,l)) continue;
|
||||||
|
|
||||||
|
if (c == Cs && l == Ls){
|
||||||
|
cout << g[c][l] << endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = -2; i <= 2; i++){
|
||||||
|
for (int j = -2; j <= 2; j++){
|
||||||
|
int nc = c + i, nl = l + j;
|
||||||
|
if (!valid(nc, nl)) continue;
|
||||||
|
|
||||||
|
int cost = COSTS[i+2][j+2];
|
||||||
|
int newG = g[c][l] + cost;
|
||||||
|
|
||||||
|
if (newG < g[nc][nl]){
|
||||||
|
g[nc][nl] = newG;
|
||||||
|
pq.push({newG + h(nc, nl), {nc, nl}});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cout << "impossible" << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
ios::sync_with_stdio(false);
|
||||||
|
cin.tie(nullptr);
|
||||||
|
|
||||||
|
while (C=get_int(), L=get_int(), C && L){
|
||||||
|
Cr = get_int();
|
||||||
|
Lr = get_int();
|
||||||
|
Cs = get_int();
|
||||||
|
Ls = get_int();
|
||||||
|
for (int i = 1; i <= C; i++){
|
||||||
|
for (int j = 1; j <= L; j++){
|
||||||
|
alagado[i][j]=0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
W = get_int();
|
||||||
|
for (int i = 0; i < W; i++){
|
||||||
|
int C1, C2, L1, L2;
|
||||||
|
C1 = get_int();
|
||||||
|
L1 = get_int();
|
||||||
|
C2 = get_int();
|
||||||
|
L2 = get_int();
|
||||||
|
for (int k = C1; k <= C2; k++)
|
||||||
|
for (int l = L1; l <= L2; l++)
|
||||||
|
alagado[k][l] = 1;
|
||||||
|
}
|
||||||
|
solve();
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
118
ra-preguicosa/src/tle3.cpp
Normal file
118
ra-preguicosa/src/tle3.cpp
Normal file
@@ -0,0 +1,118 @@
|
|||||||
|
#include <bits/stdc++.h>
|
||||||
|
|
||||||
|
#define endl '\n'
|
||||||
|
#define INF 0x3f3f3f3f
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
typedef pair<int, int> pii;
|
||||||
|
|
||||||
|
inline int get_int(){
|
||||||
|
int ch, i;
|
||||||
|
while (((ch = getchar()) == ' ') || (ch == '\n'));
|
||||||
|
for (i = 0; ch >= '0' && ch <= '9'; ch = getchar() )
|
||||||
|
i = 10 * i + (ch - '0');
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
const int MAXN = 1e3 + 10;
|
||||||
|
|
||||||
|
int C, L, W;
|
||||||
|
int Cr, Lr, Cs, Ls;
|
||||||
|
const int COSTS[5][5] = {
|
||||||
|
{7, 6, 5, 6, 7},
|
||||||
|
{6, 3, 2, 3, 6},
|
||||||
|
{5, 2, 0, 2, 5},
|
||||||
|
{6, 3, 2, 3, 6},
|
||||||
|
{7, 6, 5, 6, 7},
|
||||||
|
};
|
||||||
|
bitset<MAXN> alagado[MAXN];
|
||||||
|
int g[MAXN][MAXN];
|
||||||
|
|
||||||
|
bool valid(int c, int l) {
|
||||||
|
return c > 0 && c <= C && l > 0 && l <= L && alagado[c][l] == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int h(int c, int l) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void solve()
|
||||||
|
{
|
||||||
|
for (int i = 1; i <= C; i++){
|
||||||
|
for (int j = 1; j <= L; j++){
|
||||||
|
g[i][j] = INF;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
priority_queue<
|
||||||
|
pair<int, pii>,
|
||||||
|
vector<pair<int, pii>>,
|
||||||
|
greater<>
|
||||||
|
> pq;
|
||||||
|
|
||||||
|
g[Cr][Lr] = 0;
|
||||||
|
pq.push({h(Cr, Lr), {Cr, Lr}});
|
||||||
|
|
||||||
|
while (!pq.empty()){
|
||||||
|
auto [curCost, curCoords] = pq.top();
|
||||||
|
pq.pop();
|
||||||
|
|
||||||
|
auto [c, l] = curCoords;
|
||||||
|
|
||||||
|
if (curCost != g[c][l] ) continue;
|
||||||
|
|
||||||
|
if (c == Cs && l == Ls){
|
||||||
|
cout << g[c][l] << endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = -2; i <= 2; i++){
|
||||||
|
for (int j = -2; j <= 2; j++){
|
||||||
|
int nc = c + i, nl = l + j;
|
||||||
|
if (!valid(nc, nl)) continue;
|
||||||
|
|
||||||
|
int cost = COSTS[i+2][j+2];
|
||||||
|
int newG = g[c][l] + cost;
|
||||||
|
|
||||||
|
if (newG < g[nc][nl]){
|
||||||
|
g[nc][nl] = newG;
|
||||||
|
pq.push({newG, {nc, nl}});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cout << "impossible" << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
ios::sync_with_stdio(false);
|
||||||
|
cin.tie(nullptr);
|
||||||
|
|
||||||
|
while (C=get_int(), L=get_int(), C && L){
|
||||||
|
Cr = get_int();
|
||||||
|
Lr = get_int();
|
||||||
|
Cs = get_int();
|
||||||
|
Ls = get_int();
|
||||||
|
for (int i = 1; i <= C; i++){
|
||||||
|
for (int j = 1; j <= L; j++){
|
||||||
|
alagado[i][j]=0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
W = get_int();
|
||||||
|
for (int i = 0; i < W; i++){
|
||||||
|
int C1, C2, L1, L2;
|
||||||
|
C1 = get_int();
|
||||||
|
L1 = get_int();
|
||||||
|
C2 = get_int();
|
||||||
|
L2 = get_int();
|
||||||
|
for (int k = C1; k <= C2; k++)
|
||||||
|
for (int l = L1; l <= L2; l++)
|
||||||
|
alagado[k][l] = 1;
|
||||||
|
}
|
||||||
|
solve();
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
BIN
rod-cutting/arthur-dolival-rod-cutting-tutorial.pdf
Normal file
BIN
rod-cutting/arthur-dolival-rod-cutting-tutorial.pdf
Normal file
Binary file not shown.
55
rod-cutting/arthur-dolival-rod-cutting-tutorial.tex
Normal file
55
rod-cutting/arthur-dolival-rod-cutting-tutorial.tex
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
\documentclass[10pt]{article}
|
||||||
|
\usepackage[utf8]{inputenc}
|
||||||
|
\usepackage{amsmath,amsthm,amssymb}
|
||||||
|
\usepackage{fullpage}
|
||||||
|
\usepackage{url}
|
||||||
|
\pagenumbering{gobble}
|
||||||
|
\usepackage{hyperref}
|
||||||
|
\usepackage{graphicx}
|
||||||
|
\input{statement/preamble.tex}
|
||||||
|
|
||||||
|
\title{ Tutorial: Barras e Barras}
|
||||||
|
\author{}
|
||||||
|
\date{}
|
||||||
|
\begin{document}
|
||||||
|
\maketitle
|
||||||
|
\section{Solução do Problema}
|
||||||
|
|
||||||
|
O problema do corte de barras (\textit{Rod Cutting}) pode ser resolvido de forma eficiente por meio de \textbf{programação dinâmica}.
|
||||||
|
A ideia é decompor o problema em subproblemas menores: para cada comprimento \(L\) queremos saber qual é a melhor receita máxima que podemos obter cortando (ou não cortando) uma barra de comprimento \(L\).
|
||||||
|
|
||||||
|
\subsection{Definição do Subproblema}
|
||||||
|
|
||||||
|
Seja \(p[1 \dots n]\) o vetor de preços onde \(p[i]\) é o preço de vender um pedaço de comprimento \(i\).
|
||||||
|
Definimos:
|
||||||
|
|
||||||
|
\[
|
||||||
|
dp[L] = \text{o maior receita obtida cortando uma barra de comprimento } L.
|
||||||
|
\]
|
||||||
|
|
||||||
|
Assim, \(dp[L]\) representa a resposta ótima para uma barra de tamanho \(L\).
|
||||||
|
|
||||||
|
\subsection{Função de Transição}
|
||||||
|
|
||||||
|
Para determinar \(dp[L]\) consideramos a primeira peça que retiramos da barra: se escolhemos cortar uma peça de tamanho \(x\) (com \(1 \le x \le L\)), obtemos imediatamente o preço \(p[x]\) e ficamos com o subproblema da barra restante de tamanho \(L-x\), cujo melhor valor é \(dp[L-x]\). Logo:
|
||||||
|
|
||||||
|
\[
|
||||||
|
dp[L] = \max_{1 \le x \le L} \big( p[x] + dp[L-x] \big).
|
||||||
|
\]
|
||||||
|
|
||||||
|
Em particular, se não fizermos cortes (i.e., vendermos a barra inteira), isso corresponde ao caso \(x=L\) e é coberto pela fórmula acima.
|
||||||
|
|
||||||
|
\subsection{Casos Base}
|
||||||
|
|
||||||
|
O caso base é natural:
|
||||||
|
|
||||||
|
\[
|
||||||
|
dp[0] = 0,
|
||||||
|
\]
|
||||||
|
|
||||||
|
isto é, uma barra de comprimento zero tem receita zero.
|
||||||
|
|
||||||
|
\subsection{Recuperação da Decomposição (pedaços)}
|
||||||
|
|
||||||
|
Para além do valor máximo \(dp[n]\), frequentemente queremos também uma decomposição concreta (lista de comprimentos dos pedaços) que atinja esse valor. Para isso mantemos, durante a computação de \(dp\), um vetor auxiliar \texttt{cut[L]} que armazena o tamanho \(x\) do primeiro pedaço que produz o ótimo para \(dp[L]\). Após preencher \(dp\) e \texttt{cut}, reconstruímos os pedaços repetindo a operação: tomar \(x=\texttt{cut}[L]\), imprimir \(x\), e reduzir \(L \leftarrow L - x\), até \(L=0\).
|
||||||
|
\end{document}
|
||||||
BIN
rod-cutting/arthur-dolival-rod-cutting.pdf
Normal file
BIN
rod-cutting/arthur-dolival-rod-cutting.pdf
Normal file
Binary file not shown.
47
rod-cutting/arthur-dolival-rod-cutting.tex
Normal file
47
rod-cutting/arthur-dolival-rod-cutting.tex
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
\documentclass{maratona}
|
||||||
|
|
||||||
|
\begin{document}
|
||||||
|
\begin{ProblemaAutor}{}{Barras e Barras}{1}{256}{}
|
||||||
|
|
||||||
|
Dado um pedaço de barra de aço de comprimento \( n \) polegadas, deseja-se cortar essa barra em partes menores de forma a maximizar o lucro total obtido.
|
||||||
|
|
||||||
|
Cada corte é gratuito e o comprimento de cada pedaço resultante deve ser um número inteiro de polegadas.
|
||||||
|
|
||||||
|
É fornecida uma tabela de preços \( p_i \), onde \( p_i \) representa o preço de venda de uma barra de comprimento \( i \).
|
||||||
|
|
||||||
|
O objetivo é determinar qual é a \textbf{maior receita possível} ao cortar (ou não cortar) a barra original, bem como uma decomposição válida cujos comprimentos somados sejam exatamente \( n \) e cujo valor total seja igual à receita máxima.
|
||||||
|
|
||||||
|
\Entrada
|
||||||
|
|
||||||
|
A entrada é composta por duas linhas.
|
||||||
|
A primeira linha contém um inteiro \( n \) (\( 1 \le n \le 1000 \)), representando o comprimento da barra de aço.
|
||||||
|
A segunda linha contém \( n \) inteiros positivos \( p_1, p_2, \ldots, p_n \), onde \( 1 \le p_i \le 10000 \), e \( p_i \) indica o preço de uma barra de comprimento \( i \).
|
||||||
|
|
||||||
|
\Saida
|
||||||
|
|
||||||
|
A saída é composta por duas linhas.
|
||||||
|
Na primeira linha deve ser impresso um inteiro representando a \textbf{receita máxima} que pode ser obtida cortando a barra.
|
||||||
|
Na segunda linha deve ser impressa uma sequência de inteiros positivos representando os comprimentos dos pedaços utilizados, cuja soma deve ser exatamente \( n \).
|
||||||
|
|
||||||
|
É permitido imprimir os pedaços em qualquer ordem.
|
||||||
|
|
||||||
|
\ExemploEntrada
|
||||||
|
|
||||||
|
\begin{Exemplo}
|
||||||
|
\texttt{8} & \texttt{22}\\
|
||||||
|
\texttt{1~5~8~9~10~17~17~20} & \texttt{2~6}\\
|
||||||
|
\rowcolor{gray!20}\texttt{4} & \texttt{5}\\
|
||||||
|
\rowcolor{gray!20}\texttt{1~2~3~5} & \texttt{4}\\
|
||||||
|
\texttt{8} & \texttt{24}\\
|
||||||
|
\texttt{3~5~8~9~10~17~17~20} & \texttt{1~1~1~1~1~1~1~1}\\
|
||||||
|
\end{Exemplo}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
\Notas
|
||||||
|
|
||||||
|
No primeiro caso, a barra possui tamanho 8 e os preços fornecidos indicam o valor de venda de cada tamanho possível. A saída informa que a decomposição escolhida foi em pedaços de tamanhos 2 e 6, que somam exatamente o tamanho total da barra. O preço do pedaço de tamanho 2 é 5 e o preço do pedaço de tamanho 6 é 17, totalizando 22. Não existe nenhuma outra forma de cortar a barra que produza um valor maior do que esse, portanto a solução apresentada é ótima.
|
||||||
|
|
||||||
|
No segundo caso, a barra possui tamanho 4. O preço de venda para a barra inteira de tamanho 4 é 5. Qualquer tentativa de cortar a barra em pedaços menores resulta em um valor total inferior, já que combinações como 1+3, 2+2 ou quatro pedaços de 1 produzem lucro máximo igual a 4. Assim, o melhor é não realizar nenhum corte e vender a barra inteira. Dessa forma, o valor ótimo é 5 e a decomposição correspondente consiste apenas no pedaço de tamanho 4.
|
||||||
|
\end{ProblemaAutor}
|
||||||
|
\end{document}
|
||||||
BIN
subset-sum/arthur-dolival-subset-sum-tutorial.pdf
Normal file
BIN
subset-sum/arthur-dolival-subset-sum-tutorial.pdf
Normal file
Binary file not shown.
45
subset-sum/arthur-dolival-subset-sum-tutorial.tex
Normal file
45
subset-sum/arthur-dolival-subset-sum-tutorial.tex
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
\documentclass[10pt]{article}
|
||||||
|
\usepackage[utf8]{inputenc}
|
||||||
|
\usepackage{amsmath,amsthm,amssymb}
|
||||||
|
\usepackage{fullpage}
|
||||||
|
\usepackage{url}
|
||||||
|
\pagenumbering{gobble}
|
||||||
|
\usepackage{hyperref}
|
||||||
|
\usepackage{graphicx}
|
||||||
|
\input{statement/preamble.tex}
|
||||||
|
|
||||||
|
\title{ Tutorial: Prateleira Dourada}
|
||||||
|
\author{}
|
||||||
|
\date{}
|
||||||
|
\begin{document}
|
||||||
|
\maketitle
|
||||||
|
\section{Solução do Problema}
|
||||||
|
|
||||||
|
O problema de organizar os livros para preencher exatamente a prateleira é uma aplicação clássica do problema da \textbf{Soma de Subconjuntos} (\textit{Subset Sum}), que é uma variação do problema da Mochila (0/1 \textit{Knapsack}). Podemos resolvê-lo de forma eficiente utilizando \textbf{programação dinâmica}. A ideia é rastrear todos os comprimentos parciais possíveis que conseguimos formar com as combinações de livros avaliados até o momento.
|
||||||
|
|
||||||
|
\subsection{Definição do Subproblema}
|
||||||
|
|
||||||
|
Seja $T$ o comprimento total da prateleira.
|
||||||
|
Definimos o nosso estado da programação dinâmica como um vetor booleano:
|
||||||
|
|
||||||
|
$$dp[j] = \text{1 se for possível formar o comprimento exato } j \text{ com algum subconjunto dos livros.}$$
|
||||||
|
|
||||||
|
O nosso objetivo final é descobrir se, após testar todas as combinações de livros, o estado $dp[T]$ se torna verdadeiro.
|
||||||
|
|
||||||
|
\subsection{Função de Transição}
|
||||||
|
|
||||||
|
Para atualizar os nossos estados, iteramos e avaliamos um livro de cada vez. Seja $x$ a espessura do livro atual.
|
||||||
|
A lógica é simples: se já descobrimos que é possível formar uma pilha de livros com espessura exata $j$ (ou seja, $dp[j] == 1$), então, ao colocar esse novo livro na pilha, também seremos capazes de alcançar a espessura $j + x$.
|
||||||
|
|
||||||
|
A transição, pode ser descrita como:
|
||||||
|
|
||||||
|
$$dp[j + x] = dp[j + x] \lor dp[j]$$
|
||||||
|
|
||||||
|
\textbf{Detalhe crucial de implementação:} Para garantir que o bibliotecário use cada livro \textbf{no máximo uma vez}, precisamos percorrer as capacidades de trás para frente (começando em $T - x$ e diminuindo até $0$). Se iterássemos da esquerda para a direita, um livro poderia ser considerado mais de uma vez, o que não é o correto nesse problema.
|
||||||
|
\subsection{Casos Base}
|
||||||
|
|
||||||
|
O caso base representa a situação em que não selecionamos livro algum. A soma das espessuras de uma prateleira vazia é zero. Portanto, é sempre possível "formar" o comprimento $0$:
|
||||||
|
|
||||||
|
$$dp[0] = 1$$
|
||||||
|
|
||||||
|
Todos os outros comprimentos no vetor de $1$ a $T$ nascem como $0$ (falsos/impossíveis), pois ainda precisamos descobrir se eles podem ser alcançados utilizando os livros da pilha.\end{document}
|
||||||
BIN
subset-sum/arthur-dolival-subset-sum.pdf
Normal file
BIN
subset-sum/arthur-dolival-subset-sum.pdf
Normal file
Binary file not shown.
43
subset-sum/arthur-dolival-subset-sum.tex
Normal file
43
subset-sum/arthur-dolival-subset-sum.tex
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
\documentclass{maratona}
|
||||||
|
|
||||||
|
\begin{document}
|
||||||
|
\begin{ProblemaAutor}{}{Prateleira Dourada}{1}{256}{}
|
||||||
|
|
||||||
|
Você foi recentemente contratado como arquivista júnior na Biblioteca Central, lar de manuscritos inestimáveis. Sua primeira grande tarefa é organizar a famosa \textbf{Prateleira Dourada}, um espaço de exposição reservado apenas para as obras mais raras.
|
||||||
|
|
||||||
|
Esta prateleira possui um comprimento físico exato de $T$ centímetros. O bibliotecário-chefe, Sr. Justino, é famoso por sua exigência extrema com a estética e a preservação: ele abomina espaços vazios onde a poeira possa se acumular, mas também proíbe terminantemente que os livros sejam espremidos, o que danificaria suas capas de couro.
|
||||||
|
|
||||||
|
Para o Sr. Justino, a organização só é aceitável se a prateleira for preenchida \textbf{de ponta a ponta}, sem que sobre ou falte qualquer espaço.
|
||||||
|
|
||||||
|
Você recebeu uma pilha contendo $n$ livros raros. Cada livro possui uma espessura específica. Sua missão é verificar se existe uma seleção de livros cuja soma das espessuras seja \textbf{exatamente} igual ao comprimento $T$ da prateleira.
|
||||||
|
|
||||||
|
\Entrada
|
||||||
|
|
||||||
|
A primeira linha possui dois inteiros: $n$ ($1 \le n \le 1\,000$), representando a quantidade de livros, e $T$ ($1 \le T \le 10\,000$), o comprimento total da prateleira, em centímetros.
|
||||||
|
A segunda linha contém $n$ inteiros positivos $a_1, a_2, \dots, a_n$, as larguras dos livros em centímetros, com $1 \le a_i \le 1\,000$.
|
||||||
|
|
||||||
|
\Saida
|
||||||
|
|
||||||
|
Imprima exatamente uma linha: \texttt{PERFEITO!} caso exista um subconjunto de livros cuja soma das larguras seja exatamente $T$, ou \texttt{IMPOSSIVEL!} caso contrário.
|
||||||
|
|
||||||
|
\ExemploEntrada
|
||||||
|
|
||||||
|
\begin{Exemplo}
|
||||||
|
\texttt{5~10} & \texttt{PERFEITO!}\\
|
||||||
|
\texttt{1~2~3~4~5} & \\
|
||||||
|
\rowcolor{gray!20}\texttt{4~4} & \texttt{IMPOSSIVEL!}\\
|
||||||
|
\rowcolor{gray!20}\texttt{5~1~2~5} & \\
|
||||||
|
\texttt{8~14} & \texttt{PERFEITO!}\\
|
||||||
|
\texttt{1~2~3~4~4~9~9~15} & \\
|
||||||
|
\end{Exemplo}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
\Notas
|
||||||
|
|
||||||
|
No primeiro caso de teste é possível escolher os livros de comprimentos 2, 3 e 5.
|
||||||
|
|
||||||
|
No segundo caso de teste nenhuma combinação de livros resultará no comprimento da prateleira.
|
||||||
|
|
||||||
|
No Terceiro caso de teste é possível escolher os livros de comprimentos 9, 4, e 1. Outra opção seriam os livros de comprimentos 1, 2, 3, 4, 4.\end{ProblemaAutor}
|
||||||
|
\end{document}
|
||||||
BIN
vacations/arthur-dolival-vacations-tutorial.pdf
Normal file
BIN
vacations/arthur-dolival-vacations-tutorial.pdf
Normal file
Binary file not shown.
61
vacations/arthur-dolival-vacations-tutorial.tex
Normal file
61
vacations/arthur-dolival-vacations-tutorial.tex
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
\documentclass[10pt]{article}
|
||||||
|
\usepackage[utf8]{inputenc}
|
||||||
|
\usepackage{amsmath,amsthm,amssymb}
|
||||||
|
\usepackage{fullpage}
|
||||||
|
\usepackage{url}
|
||||||
|
\pagenumbering{gobble}
|
||||||
|
\usepackage{hyperref}
|
||||||
|
\usepackage{graphicx}
|
||||||
|
\input{statement/preamble.tex}
|
||||||
|
|
||||||
|
\title{ Tutorial: Férias}
|
||||||
|
\author{Codeforces 363 (Div. 1)}
|
||||||
|
\date{}
|
||||||
|
\begin{document}
|
||||||
|
\maketitle
|
||||||
|
\section{Solução do Problema}
|
||||||
|
|
||||||
|
O problema de planejar as férias de Miguel para minimizar os dias de descanso, respeitando a regra de não repetir a mesma atividade física ou mental em dias consecutivos, pode ser resolvido de forma muito eficiente usando \textbf{programação dinâmica}. A intuição é que a decisão do que fazer no dia atual depende exclusivamente da disponibilidade de atividades no dia e do que Miguel escolheu fazer no dia imediatamente anterior.
|
||||||
|
|
||||||
|
\subsection{Definição do Subproblema}
|
||||||
|
|
||||||
|
Como a restrição olha apenas para a atividade do dia anterior, precisamos carregar essa informação no nosso estado. Definimos o nosso estado da programação dinâmica como:
|
||||||
|
|
||||||
|
dp[i][j] = \text{o número mínimo de dias de descanso acumulados até o dia } i, \text{ dado que a atividade escolhida no dia } i \text{ foi } j.
|
||||||
|
|
||||||
|
Mapeamos os possíveis valores de $j$ (as escolhas de Miguel) da seguinte forma:
|
||||||
|
\begin{itemize}
|
||||||
|
\item $j = 0$: Descansar
|
||||||
|
\item $j = 1$: Participar de uma competição
|
||||||
|
\item $j = 2$: Ir à academia
|
||||||
|
\end{itemize}
|
||||||
|
|
||||||
|
A resposta final para o problema será o menor valor entre todas as atividades possíveis no último dia de férias: $\min(dp[n][0], dp[n][1], dp[n][2])$.
|
||||||
|
|
||||||
|
\subsection{Função de Transição}
|
||||||
|
|
||||||
|
Para calcular as opções do dia $i$, olhamos para os melhores resultados alcançados no dia $i-1$ e verificamos o que o calendário ($A[i]$) nos permite fazer hoje.
|
||||||
|
|
||||||
|
\textbf{1. Descansar ($j = 0$):}
|
||||||
|
Miguel sempre pode descansar em qualquer dia, independentemente do que ele fez ontem. Como descansar adiciona $1$ ao nosso contador de dias de descanso, a transição é:
|
||||||
|
$$dp[i][0] = \min \big( dp[i-1][0], dp[i-1][1], dp[i-1][2] \big) + 1$$
|
||||||
|
|
||||||
|
\textbf{2. Competir ($j = 1$):}
|
||||||
|
Miguel só pode competir se houver competição hoje ($A[i] == 1$ ou $A[i] == 3$). Além disso, ele não pode ter competido ontem. Logo, os estados válidos anteriores são apenas descanso ($0$) ou academia ($2$):
|
||||||
|
$$dp[i][1] = \min \big( dp[i-1][0], dp[i-1][2] \big)$$
|
||||||
|
\textit{Se não houver competição hoje, definimos o estado como inalcançável ($dp[i][1] = \infty$).}
|
||||||
|
|
||||||
|
\textbf{3. Ir à academia ($j = 2$):}
|
||||||
|
De forma análoga, Miguel só pode treinar se a academia estiver aberta ($A[i] == 2$ ou $A[i] == 3$) e se ele não tiver ido à academia ontem. Os estados válidos anteriores são descanso ($0$) ou competição ($1$):
|
||||||
|
$$dp[i][2] = \min \big( dp[i-1][0], dp[i-1][1] \big)$$
|
||||||
|
\textit{Se a academia estiver fechada hoje, definimos o estado como inalcançável ($dp[i][2] = \infty$).}
|
||||||
|
|
||||||
|
\subsection{Casos Base}
|
||||||
|
|
||||||
|
Para que as transições do primeiro dia de férias ($i = 1$) funcionem corretamente, inicializamos o dia $0$ (o momento anterior ao início das férias).
|
||||||
|
|
||||||
|
Como antes das férias começarem não há nenhum dia de descanso acumulado, independentemente da atividade "fictícia" que possamos imaginar, zeramos os estados iniciais:
|
||||||
|
|
||||||
|
$$dp[0][0] = 0$$
|
||||||
|
$$dp[0][1] = 0$$
|
||||||
|
$$dp[0][2] = 0$$\end{document}
|
||||||
BIN
vacations/arthur-dolival-vacations.pdf
Normal file
BIN
vacations/arthur-dolival-vacations.pdf
Normal file
Binary file not shown.
48
vacations/arthur-dolival-vacations.tex
Normal file
48
vacations/arthur-dolival-vacations.tex
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
\documentclass{maratona}
|
||||||
|
|
||||||
|
\begin{document}
|
||||||
|
\begin{ProblemaAutor}{}{Férias}{1}{256}{Codeforces 363 (Div. 1)}
|
||||||
|
|
||||||
|
Miguel tem \(n\) dias de férias e pretende aproveitá-los para estudar programação e também praticar esportes. Para cada um desses dias, ele sabe antecipadamente duas informações: se a academia estará aberta e se haverá uma competição online disponível. Assim, cada dia se enquadra em uma das quatro situações possíveis: sem academia e sem competição, sem academia mas com competição, com academia mas sem competição, ou com ambos disponíveis.
|
||||||
|
|
||||||
|
Em cada dia, Miguel deve escolher exatamente uma ação: descansar, participar da competição (caso ele exista naquele dia) ou ir à academia (caso esteja aberta). Seu objetivo é descansar o mínimo possível. No entanto, ele impõe a si mesmo uma regra importante: \textbf{não repetir a mesma atividade em dias consecutivos}. Em outras palavras, Miguel não aceita fazer esporte dois dias seguidos, nem participar de competições em dias consecutivos, embora descansar possa ocorrer repetidamente sem qualquer restrição.
|
||||||
|
|
||||||
|
Dado o calendário das férias, determine o menor número de dias de descanso que Miguel será obrigado a ter.
|
||||||
|
|
||||||
|
\Entrada
|
||||||
|
|
||||||
|
A primeira linha contém um inteiro positivo \(n\) (\(1 \le n \le 100\)), o número de dias de férias.
|
||||||
|
|
||||||
|
A segunda linha contém \(n\) inteiros \(a_1, a_2, \dots, a_n\) (\(0 \le a_i \le 3\)), separados por espaços, onde cada \(a_i\) descreve as opções do \(i\)-ésimo dia:
|
||||||
|
\begin{itemize}
|
||||||
|
\item \(a_i = 0\): academia fechada e sem competição;
|
||||||
|
\item \(a_i = 1\): academia fechada e há competição;
|
||||||
|
\item \(a_i = 2\): academia aberta e sem competição;
|
||||||
|
\item \(a_i = 3\): academia aberta e há competição.
|
||||||
|
\end{itemize}
|
||||||
|
|
||||||
|
\Saida
|
||||||
|
|
||||||
|
A saída consiste de um único número inteiro, o número mínimo possível de dias em que Miguel terá que descansar, obedecendo à restrição de não repetir a mesma atividade em dias consecutivos.
|
||||||
|
|
||||||
|
\ExemploEntrada
|
||||||
|
|
||||||
|
\begin{Exemplo}
|
||||||
|
\texttt{4} & \texttt{2}\\
|
||||||
|
\texttt{1~3~2~0} & \\
|
||||||
|
\rowcolor{gray!20}\texttt{7} & \texttt{0}\\
|
||||||
|
\rowcolor{gray!20}\texttt{1~3~3~2~1~2~3} & \\
|
||||||
|
\texttt{2} & \texttt{1}\\
|
||||||
|
\texttt{2~2} & \\
|
||||||
|
\end{Exemplo}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
\Notas
|
||||||
|
|
||||||
|
No primeiro caso de teste, Miguel pode participar da competição no dia 1 e ir à academia no dia 3. Descansando nos dias 2 e 4.
|
||||||
|
|
||||||
|
No segundo caso de teste, Miguel pode participar da competição nos dias 1, 3, 5 e 7 e ir à academia nos demais.
|
||||||
|
|
||||||
|
No terceiro caso de teste, como Miguel não pode ir à academia em dois dias seguidos ele será obrigado a descansar em um dos dias.\end{ProblemaAutor}
|
||||||
|
\end{document}
|
||||||
Reference in New Issue
Block a user