feat: added WA and TLE solutions to delete-and-earn problem, also wrote the tutorial file
This commit is contained in:
BIN
delete-and-earn/delete-and-earn-tutorial.pdf
Normal file
BIN
delete-and-earn/delete-and-earn-tutorial.pdf
Normal file
Binary file not shown.
64
delete-and-earn/delete-and-earn-tutorial.tex
Normal file
64
delete-and-earn/delete-and-earn-tutorial.tex
Normal file
@@ -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}
|
||||||
Binary file not shown.
@@ -44,8 +44,8 @@
|
|||||||
"solutions": {
|
"solutions": {
|
||||||
"main-ac": "ac.cpp",
|
"main-ac": "ac.cpp",
|
||||||
"alternative-ac": [],
|
"alternative-ac": [],
|
||||||
"wrong-answer": [],
|
"wrong-answer": ["WA.cpp"],
|
||||||
"time-limit": [],
|
"time-limit": ["TLE.cpp"],
|
||||||
"time-limit-or-ac": [],
|
"time-limit-or-ac": [],
|
||||||
"time-limit-or-memory-limit": [],
|
"time-limit-or-memory-limit": [],
|
||||||
"memory-limit": [],
|
"memory-limit": [],
|
||||||
|
|||||||
44
delete-and-earn/src/TLE.cpp
Normal file
44
delete-and-earn/src/TLE.cpp
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
#include <bits/stdc++.h>
|
||||||
|
|
||||||
|
typedef long long ll;
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
int findMaxPoints(vector<int>& 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<int>& nums) {
|
||||||
|
int maxValue = nums[0];
|
||||||
|
for (int i = 0; i < nums.size(); ++i) {
|
||||||
|
maxValue = max(maxValue, nums[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
vector<int> 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<int> nums(n);
|
||||||
|
for (int i = 0; i < n; i++)
|
||||||
|
cin >> nums[i];
|
||||||
|
cout << deleteAndEarn(nums) << endl;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
37
delete-and-earn/src/WA.cpp
Normal file
37
delete-and-earn/src/WA.cpp
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
#include <bits/stdc++.h>
|
||||||
|
|
||||||
|
typedef long long ll;
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
int deleteAndEarn(vector<int> &nums)
|
||||||
|
{
|
||||||
|
int sum = 0;
|
||||||
|
map<int, int> 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<int> nums(n);
|
||||||
|
for (int i = 0; i < n; i++)
|
||||||
|
cin >> nums[i];
|
||||||
|
cout << deleteAndEarn(nums) << endl;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -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}
|
||||||
Reference in New Issue
Block a user