diff --git a/knapsack-zero-one/knapsack-zero-one-tutorial.pdf b/knapsack-zero-one/knapsack-zero-one-tutorial.pdf new file mode 100644 index 0000000..aca538b Binary files /dev/null and b/knapsack-zero-one/knapsack-zero-one-tutorial.pdf differ diff --git a/knapsack-zero-one/knapsack-zero-one-tutorial.tex b/knapsack-zero-one/knapsack-zero-one-tutorial.tex new file mode 100644 index 0000000..32d48ff --- /dev/null +++ b/knapsack-zero-one/knapsack-zero-one-tutorial.tex @@ -0,0 +1,70 @@ +\documentclass[10pt]{article} +\usepackage[utf8]{inputenc} +\usepackage{amsmath,amsthm,amssymb} +\usepackage{fullpage} +\usepackage{url} +\pagenumbering{gobble} +\usepackage{hyperref} + +\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} diff --git a/knapsack-zero-one/knapsack-zero-one.pdf b/knapsack-zero-one/knapsack-zero-one.pdf index 1f9a2b6..f8f2564 100644 Binary files a/knapsack-zero-one/knapsack-zero-one.pdf and b/knapsack-zero-one/knapsack-zero-one.pdf differ diff --git a/knapsack-zero-one/problem.json b/knapsack-zero-one/problem.json index feed1c4..f8c7b63 100644 --- a/knapsack-zero-one/problem.json +++ b/knapsack-zero-one/problem.json @@ -11,10 +11,10 @@ "grader": false, "subject": { "en_us": [ - "dynamic-programming" + "dynamic-programming", "knapsack-problem", "knapsack-0/1" ], "pt_br": [ - "programação-dinâmica" + "programação-dinâmica", "problema-da-mochila", "problema-da-mochila-booleano" ], "es": [ "" diff --git a/knapsack-zero-one/src/TLE.cpp b/knapsack-zero-one/src/TLE.cpp index 2ff9624..d4b5f32 100644 --- a/knapsack-zero-one/src/TLE.cpp +++ b/knapsack-zero-one/src/TLE.cpp @@ -1,34 +1,30 @@ #include using namespace std; -typedef long long ll; +using ll = long long; + +int N; +ll W; +vector weight, value; + +ll knapsack(int i, ll w) { + if (i == 0 || w == 0) return 0; + + ll res = knapsack(i - 1, w); + if (weight[i] <= w) + res = max(res, value[i] + knapsack(i - 1, w - weight[i])); + + return res; +} + int main() { - int N, W; cin >> N >> W; - vector> items(N+1); - for (int i = 1; i <= N; i++) { - ll wi, vi; cin >> wi >> vi; - items[i] = {wi, vi}; - } + cin >> N >> W; + weight.resize(N + 1); + value.resize(N + 1); - ll ans = 0; - for (ll i = 0; i < (1<> j) & 1)) { - if (capacity >= wj) { - capacity -= wj; - value += vj; - } else { - value = -1; - break; - } - } - } - ans = max(ans, value); - } - - cout << ans << endl; + for (int i = 1; i <= N; i++) + cin >> weight[i] >> value[i]; + cout << knapsack(N, W) << "\n"; return 0; -} \ No newline at end of file +} diff --git a/knapsack-zero-one/statement/tutorial.tex b/knapsack-zero-one/statement/tutorial.tex index e69de29..32a5ebf 100644 --- a/knapsack-zero-one/statement/tutorial.tex +++ b/knapsack-zero-one/statement/tutorial.tex @@ -0,0 +1,56 @@ +\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.