feat: new tutorial file, TLE solution updated
This commit is contained in:
BIN
knapsack-zero-one/knapsack-zero-one-tutorial.pdf
Normal file
BIN
knapsack-zero-one/knapsack-zero-one-tutorial.pdf
Normal file
Binary file not shown.
70
knapsack-zero-one/knapsack-zero-one-tutorial.tex
Normal file
70
knapsack-zero-one/knapsack-zero-one-tutorial.tex
Normal file
@@ -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}
|
||||||
Binary file not shown.
@@ -11,10 +11,10 @@
|
|||||||
"grader": false,
|
"grader": false,
|
||||||
"subject": {
|
"subject": {
|
||||||
"en_us": [
|
"en_us": [
|
||||||
"dynamic-programming"
|
"dynamic-programming", "knapsack-problem", "knapsack-0/1"
|
||||||
],
|
],
|
||||||
"pt_br": [
|
"pt_br": [
|
||||||
"programação-dinâmica"
|
"programação-dinâmica", "problema-da-mochila", "problema-da-mochila-booleano"
|
||||||
],
|
],
|
||||||
"es": [
|
"es": [
|
||||||
""
|
""
|
||||||
|
|||||||
@@ -1,34 +1,30 @@
|
|||||||
#include <bits/stdc++.h>
|
#include <bits/stdc++.h>
|
||||||
using namespace std;
|
using namespace std;
|
||||||
typedef long long ll;
|
using ll = long long;
|
||||||
|
|
||||||
|
int N;
|
||||||
|
ll W;
|
||||||
|
vector<ll> 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 main() {
|
||||||
int N, W; cin >> N >> W;
|
cin >> N >> W;
|
||||||
vector<pair<ll,ll>> items(N+1);
|
weight.resize(N + 1);
|
||||||
for (int i = 1; i <= N; i++) {
|
value.resize(N + 1);
|
||||||
ll wi, vi; cin >> wi >> vi;
|
|
||||||
items[i] = {wi, vi};
|
|
||||||
}
|
|
||||||
|
|
||||||
ll ans = 0;
|
for (int i = 1; i <= N; i++)
|
||||||
for (ll i = 0; i < (1<<N); i++) {
|
cin >> weight[i] >> value[i];
|
||||||
ll capacity = W, value = 0;
|
|
||||||
for (int j = 0; j < N; j++) {
|
|
||||||
auto [wj, vj] = items[j + 1];
|
|
||||||
if (((i >> j) & 1)) {
|
|
||||||
if (capacity >= wj) {
|
|
||||||
capacity -= wj;
|
|
||||||
value += vj;
|
|
||||||
} else {
|
|
||||||
value = -1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ans = max(ans, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
cout << ans << endl;
|
|
||||||
|
|
||||||
|
cout << knapsack(N, W) << "\n";
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -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.
|
||||||
|
|||||||
Reference in New Issue
Block a user