diff --git a/delete-and-earn/delete-and-earn-tutorial.pdf b/delete-and-earn/delete-and-earn-tutorial.pdf new file mode 100644 index 0000000..cde11c1 Binary files /dev/null and b/delete-and-earn/delete-and-earn-tutorial.pdf differ diff --git a/delete-and-earn/delete-and-earn-tutorial.tex b/delete-and-earn/delete-and-earn-tutorial.tex new file mode 100644 index 0000000..bd0c1d2 --- /dev/null +++ b/delete-and-earn/delete-and-earn-tutorial.tex @@ -0,0 +1,64 @@ +\documentclass[10pt]{article} +\usepackage[utf8]{inputenc} +\usepackage{amsmath,amsthm,amssymb} +\usepackage{fullpage} +\usepackage{url} +\pagenumbering{gobble} +\usepackage{hyperref} + +\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} diff --git a/delete-and-earn/delete-and-earn.pdf b/delete-and-earn/delete-and-earn.pdf index a060eff..e20c517 100644 Binary files a/delete-and-earn/delete-and-earn.pdf and b/delete-and-earn/delete-and-earn.pdf differ diff --git a/delete-and-earn/problem.json b/delete-and-earn/problem.json index 9cbd016..2c7b300 100644 --- a/delete-and-earn/problem.json +++ b/delete-and-earn/problem.json @@ -44,8 +44,8 @@ "solutions": { "main-ac": "ac.cpp", "alternative-ac": [], - "wrong-answer": [], - "time-limit": [], + "wrong-answer": ["WA.cpp"], + "time-limit": ["TLE.cpp"], "time-limit-or-ac": [], "time-limit-or-memory-limit": [], "memory-limit": [], diff --git a/delete-and-earn/src/TLE.cpp b/delete-and-earn/src/TLE.cpp new file mode 100644 index 0000000..519d636 --- /dev/null +++ b/delete-and-earn/src/TLE.cpp @@ -0,0 +1,44 @@ +#include + +typedef long long ll; +using namespace std; + +int findMaxPoints(vector& values, int i) { + if (i == 0) { + return values[0]; + } + + if (i == 1) { + return max(values[0], values[1]); + } + + // findMaxPoints(values, i - 1) means you don't take values[i]. + // findMaxPoints(values, i - 2) + values[i] means you take values[i]. + // Then, the max points you can get is the larger one of the two cases. + return max(findMaxPoints(values, i - 1), findMaxPoints(values, i - 2) + values[i]); +} + +int deleteAndEarn(vector& nums) { + int maxValue = nums[0]; + for (int i = 0; i < nums.size(); ++i) { + maxValue = max(maxValue, nums[i]); + } + + vector values(maxValue + 1, 0); + for (int i = 0; i < nums.size(); ++i) { + values[nums[i]] += nums[i]; + } + + return findMaxPoints(values, values.size() - 1); +} + +int main() +{ + int n; + cin >> n; + vector nums(n); + for (int i = 0; i < n; i++) + cin >> nums[i]; + cout << deleteAndEarn(nums) << endl; + return 0; +} \ No newline at end of file diff --git a/delete-and-earn/src/WA.cpp b/delete-and-earn/src/WA.cpp new file mode 100644 index 0000000..10b006c --- /dev/null +++ b/delete-and-earn/src/WA.cpp @@ -0,0 +1,37 @@ +#include + +typedef long long ll; +using namespace std; + +int deleteAndEarn(vector &nums) +{ + int sum = 0; + map quantity; + for (int n : nums) + { + sum += n; + quantity[n]++; + } + + int maxSum = INT_MIN; + for (const auto &pair : quantity) + { + int currentSum = sum, n = pair.first; + if (quantity.count(n - 1)) + currentSum -= quantity[n - 1] * (n - 1); + if (quantity.count(n + 1)) + currentSum -= quantity[n + 1] * (n + 1); + maxSum = max(maxSum, currentSum); + } + return maxSum; +} +int main() +{ + int n; + cin >> n; + vector nums(n); + for (int i = 0; i < n; i++) + cin >> nums[i]; + cout << deleteAndEarn(nums) << endl; + return 0; +} \ No newline at end of file diff --git a/delete-and-earn/statement/tutorial.tex b/delete-and-earn/statement/tutorial.tex index e69de29..97e2754 100644 --- a/delete-and-earn/statement/tutorial.tex +++ b/delete-and-earn/statement/tutorial.tex @@ -0,0 +1,51 @@ +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} \ No newline at end of file