Revision continues

This commit is contained in:
Antti H S Laaksonen 2017-05-24 23:55:01 +03:00
parent 355aef958e
commit ace73e0bf5
1 changed files with 73 additions and 77 deletions

View File

@ -516,41 +516,26 @@ with $N=64$ (\texttt{long long} numbers).
\section{Dynamic programming} \section{Dynamic programming}
Bit operations provide an efficient way to Bit operations provide an efficient and convenient
implement dynamic programming algorithms way to implement dynamic programming algorithms
whose states contain subsets of elements, whose states contain subsets of elements,
because such states can be stored as integers. because such states can be stored as integers.
In particular, information about all subsets Next we discuss some examples of combining
of $n$ elements can be stored in an array like bit operations and dynamic programming.
\begin{lstlisting}
int value[1<<n];
\end{lstlisting}
The following code also has an useful property:
\begin{lstlisting}
for (int b = 0; b < (1<<n); b++) {
// code
}
\end{lstlisting}
If we go through subsets in this order,
we always process subset $A$ before subset $B$
if $A \subset B$, which may be useful
in dynamic programming.
Next we discuss some examples where bit operations
and dynamic programming can be combined.
\subsubsection{Paths in a grid} \subsubsection{Paths in a grid}
As a first example, consider a problem As a first example, consider
where an $n \times n$ grid is given such that an $n \times n$ grid where
each square contains an integer $0 \ldots k$. each square contains an integer.
Our task is to check if there is a path from the upper-left Our task is to check if there is a path from the upper-left
corner to the lower-right corner corner to the lower-right corner
such that we only move right and down such that we only move right and down
and each integer $0 \ldots k$ appears on the path. and each integer between 0 and $k$ appears on the path.
For example, the following path contains all For example, in the following grid,
integers $0 \ldots 4$: there is a path that contains all
integers between 0 and $k$:
\begin{center} \begin{center}
\begin{tikzpicture}[scale=.65] \begin{tikzpicture}[scale=.65]
\begin{scope} \begin{scope}
@ -566,8 +551,8 @@ integers $0 \ldots 4$:
\draw (0, 4) grid (5, 9); \draw (0, 4) grid (5, 9);
\node at (0.5,8.5) {2}; \node at (0.5,8.5) {2};
\node at (1.5,8.5) {0}; \node at (1.5,8.5) {0};
\node at (2.5,8.5) {5}; \node at (2.5,8.5) {3};
\node at (3.5,8.5) {3}; \node at (3.5,8.5) {1};
\node at (4.5,8.5) {1}; \node at (4.5,8.5) {1};
\node at (0.5,7.5) {0}; \node at (0.5,7.5) {0};
\node at (1.5,7.5) {1}; \node at (1.5,7.5) {1};
@ -579,8 +564,8 @@ integers $0 \ldots 4$:
\node at (2.5,6.5) {2}; \node at (2.5,6.5) {2};
\node at (3.5,6.5) {4}; \node at (3.5,6.5) {4};
\node at (4.5,6.5) {1}; \node at (4.5,6.5) {1};
\node at (0.5,5.5) {6}; \node at (0.5,5.5) {2};
\node at (1.5,5.5) {5}; \node at (1.5,5.5) {1};
\node at (2.5,5.5) {0}; \node at (2.5,5.5) {0};
\node at (3.5,5.5) {1}; \node at (3.5,5.5) {1};
\node at (4.5,5.5) {3}; \node at (4.5,5.5) {3};
@ -594,34 +579,45 @@ integers $0 \ldots 4$:
\end{center} \end{center}
We assume that the rows and columns are numbered We assume that the rows and columns are numbered
from 1 to $n$. Moreover, let $\texttt{value}[x][y]$ from 1 to $n$, and $\texttt{value}[x][y]$
denote the value at position $(x,y)$. denotes the value at position $(x,y)$.
The problem can be solved in $O(n^2 2^k)$ time It turns out that the problem can be solved in $O(n^2 2^k)$ time
by defining a function $\texttt{possible}[x][y][S]$ using dynamic programming.
whose value is true exactly when there is a path
Let $\texttt{possible}(x,y,S)$ be a function
that indicates whether there is a path
from the upper-left square to square $(x,y)$ such that from the upper-left square to square $(x,y)$ such that
all values in $S$ appear on the path. all values in $S$ appear on the path.
Thus, $\texttt{possible}[n][n][\{0 \ldots k\}]$ Thus, $\texttt{possible}(n,n,\{0 \ldots k\})$
tells us whether a desired path exists. tells us whether a desired path exists.
The function values can be calculated using The values of the function can be calculated using
the following recurrence: the following recurrence:
\begin{equation*} \begin{equation*}
\begin{aligned} \begin{aligned}
\texttt{possible}[x][y][\emptyset] & = & \textrm{true} \\ \texttt{possible}(x,y,\emptyset) & = & \textrm{true} \\
\texttt{possible}[x][y][S] & = & \texttt{possible}[x-1][y][S \setminus \texttt{value}[x][y]] \lor \\ \texttt{possible}(x,y,S) & = & \texttt{possible}(x-1,y,S \setminus \texttt{value}[x][y]) \lor \\
& & \texttt{possible}[x][y-1][S \setminus \texttt{value}[x][y]] \\ & & \texttt{possible}(x,y-1,S \setminus \texttt{value}[x][y]) \\
\end{aligned} \end{aligned}
\end{equation*} \end{equation*}
The base case states that there is always a path that The base case states that there is always a path that
does not contain any digits. does not contain any integers.
Then, in the recursive case we remove $\texttt{value}[x][y]$ Then, in the recursive case we consider both directions
and remove $\texttt{value}[x][y]$
from $S$, because we can collect it in square $(x,y)$. from $S$, because we can collect it in square $(x,y)$.
The dynamic programming implementation is as follows: We can implement the dynamic programming using an array
\begin{lstlisting} \begin{lstlisting}
for (int x = 1; x <= n; x++) { bool possible[N][N][1<<K];
for (int y = 1; y <= n; y++) { \end{lstlisting}
for (int b = 0; b < (1<<k); b++) { where $N$ and $K$ are suitably large constants.
Then, we can calculate the values
of the function as follows:
\begin{lstlisting}
for (int x = 0; x <= n; x++) {
for (int y = 0; y <= n; y++) {
possible[x][y][0] = true;
if (x == 0 || y == 0) continue;
for (int b = 1; b < (1<<k); b++) {
possible[x][y][b] = possible[x-1][y][b&~value[x][y]] || possible[x][y][b] = possible[x-1][y][b&~value[x][y]] ||
possible[x][y-1][b&~value[x][y]]; possible[x][y-1][b&~value[x][y]];
} }
@ -633,19 +629,15 @@ for (int x = 1; x <= n; x++) {
Using dynamic programming, it is often possible Using dynamic programming, it is often possible
to change an iteration over permutations into to change an iteration over permutations into
an iteration over subsets, so that an iteration over subsets\footnote{This technique was introduced in 1962
the dynamic programming state
contains a subset of a set and possibly
some additional information\footnote{This technique was introduced in 1962
by M. Held and R. M. Karp \cite{hel62}.}. by M. Held and R. M. Karp \cite{hel62}.}.
The benefit of this technique is that
The benefit of this is that
$n!$, the number of permutations of an $n$ element set, $n!$, the number of permutations of an $n$ element set,
is much larger than $2^n$, the number of subsets is much larger than $2^n$, the number of subsets
of the same set. of the same set.
For example, if $n=20$, then For example, if $n=20$, then
$n! \approx 2.4 \cdot 10^{18}$ and $2^n \approx 10^6$. $n! \approx 2.4 \cdot 10^{18}$ and $2^n \approx 10^6$.
Hence, for certain values of $n$, Thus, for certain values of $n$,
we can efficiently go through subsets but not through permutations. we can efficiently go through subsets but not through permutations.
As an example, consider the following problem: As an example, consider the following problem:
@ -683,8 +675,8 @@ The idea is to calculate for each subset of people
two values: the minimum number of rides needed and two values: the minimum number of rides needed and
the minimum weight of people who ride in the last group. the minimum weight of people who ride in the last group.
Let $\texttt{rides}(X)$ denote the minimum number Let $\texttt{rides}(X)$ and $\texttt{weight}(X)$ denote
of rides and $\texttt{weight}(X)$ denote the minimum the minimum number of rides and the minimum
weight of the last group, where $X$ is a subset weight of the last group, where $X$ is a subset
of people. For example, of people. For example,
\[ \texttt{rides}(\{B,D,E\})=2 \hspace{10px} \textrm{and} \[ \texttt{rides}(\{B,D,E\})=2 \hspace{10px} \textrm{and}
@ -695,7 +687,7 @@ Of course, our final goal is to calculate the value
of $\texttt{rides}(\{A,B,C,D,E\})$ that is the solution of $\texttt{rides}(\{A,B,C,D,E\})$ that is the solution
to the problem. to the problem.
It turns out that we can calculate the values We can calculate the values
of the functions recursively and then apply of the functions recursively and then apply
dynamic programming. dynamic programming.
The idea is to go through all people The idea is to go through all people
@ -707,31 +699,35 @@ who enters the elevator.
Each such choice yields a subproblem Each such choice yields a subproblem
for a smaller subset of people. for a smaller subset of people.
Note that we can use a loop like
\begin{lstlisting}
for (int b = 0; b < (1<<n); b++) {
// process subset b
}
\end{lstlisting}
to go through the subsets,
because if $X$ and $Y$ are two subsets
and $X \subset Y$,
then $X$ comes before $Y$ in the above order.
\subsubsection{Counting subsets} \subsubsection{Counting subsets}
Our last problem in this chapter is as follows: Our last problem in this chapter is as follows:
We are given a collection $C$ that consists of $m$ sets, Let $X=\{0,1,\ldots,n-1\}$, and each subset $S \subset X$,
and our task is to determine for each set is assigned an integer $\texttt{value}(S)$.
the number of sets in $C$ that are its subsets. Our task is to calculate for each $S$
For example, consider the following collection: \[\texttt{sum}(S) = \sum_{A \subset S} \texttt{value}(A),\]
\[C = \{\{0\}, \{0,2\}, \{1,4\}, \{0,1,4\}, \{1,4,5\}\}\] i.e., the sum of values of subsets of $S$.
For any set $x$ in $C$,
let $f(x)$ denote the number of sets (including $x$) in $C$ Because there are a total of $2^n$ subsets,
that are subsets of $x$. one possible solution is to go through all
For example, $f(\{0,1,4\})=3$, because the pairs of subsets in $O(2^{2n})$ time.
sets $\{0\}$, $\{1,4\}$ and $\{0,1,4\}$ are However, using dynamic programming, we
subsets of $\{0,1,4\}$. can solve the problem in $O(2^n n)$ time.
Using this notation, our task is to calculate the value of $f(x)$
for every set $x$ in the collection. Let $\texttt{sum}(S,k)$ denote the sum of
values of subsets of $S$
We will assume that each set is
a subset of $\{0,1,\ldots,n-1\}$.
Thus, the collection can contain at most
$2^n$ sets.
A straightforward way to solve the problem
is to go through all pairs of sets in the collection.
However, a more efficient solution is possible
using dynamic programming.
Let $c(x,k)$ denote the number of sets in Let $c(x,k)$ denote the number of sets in
$C$ that equal a set $x$ $C$ that equal a set $x$