diff --git a/subset-sum/problem.json b/subset-sum/problem.json index 007e634..923f86a 100644 --- a/subset-sum/problem.json +++ b/subset-sum/problem.json @@ -1,7 +1,7 @@ { "version": "1.0", "problem": { - "title": "", + "title": "Prateleira Dourada", "event": "", "time_limit": 1.0, "memory_limit_mb": 256, diff --git a/subset-sum/statement/tutorial.tex b/subset-sum/statement/tutorial.tex index e69de29..16d9303 100644 --- a/subset-sum/statement/tutorial.tex +++ b/subset-sum/statement/tutorial.tex @@ -0,0 +1,30 @@ +\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. \ No newline at end of file diff --git a/subset-sum/subset-sum-tutorial.pdf b/subset-sum/subset-sum-tutorial.pdf new file mode 100644 index 0000000..dd6969a Binary files /dev/null and b/subset-sum/subset-sum-tutorial.pdf differ diff --git a/subset-sum/subset-sum-tutorial.tex b/subset-sum/subset-sum-tutorial.tex new file mode 100644 index 0000000..4d4cf4c --- /dev/null +++ b/subset-sum/subset-sum-tutorial.tex @@ -0,0 +1,43 @@ +\documentclass[10pt]{article} +\usepackage[utf8]{inputenc} +\usepackage{amsmath,amsthm,amssymb} +\usepackage{fullpage} +\usepackage{url} +\pagenumbering{gobble} +\usepackage{hyperref} + +\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} diff --git a/subset-sum/subset-sum.pdf b/subset-sum/subset-sum.pdf index 5c45a4c..00cb357 100644 Binary files a/subset-sum/subset-sum.pdf and b/subset-sum/subset-sum.pdf differ diff --git a/subset-sum/subset-sum.tex b/subset-sum/subset-sum.tex index 8dfd154..22ede70 100644 --- a/subset-sum/subset-sum.tex +++ b/subset-sum/subset-sum.tex @@ -1,7 +1,7 @@ \documentclass{maratona} \begin{document} -\begin{ProblemaAutor}{}{}{1}{256}{} +\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. diff --git a/vacations/statement/tutorial.tex b/vacations/statement/tutorial.tex index e69de29..1d77618 100644 --- a/vacations/statement/tutorial.tex +++ b/vacations/statement/tutorial.tex @@ -0,0 +1,46 @@ +\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$$ \ No newline at end of file diff --git a/vacations/vacations-tutorial.pdf b/vacations/vacations-tutorial.pdf new file mode 100644 index 0000000..f6a93bc Binary files /dev/null and b/vacations/vacations-tutorial.pdf differ diff --git a/vacations/vacations-tutorial.tex b/vacations/vacations-tutorial.tex new file mode 100644 index 0000000..25f03a6 --- /dev/null +++ b/vacations/vacations-tutorial.tex @@ -0,0 +1,59 @@ +\documentclass[10pt]{article} +\usepackage[utf8]{inputenc} +\usepackage{amsmath,amsthm,amssymb} +\usepackage{fullpage} +\usepackage{url} +\pagenumbering{gobble} +\usepackage{hyperref} + +\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} diff --git a/vacations/vacations.pdf b/vacations/vacations.pdf index 2698daa..b1ed9fd 100644 Binary files a/vacations/vacations.pdf and b/vacations/vacations.pdf differ