Improve language

This commit is contained in:
Antti H S Laaksonen 2017-05-19 22:24:07 +03:00
parent e08db81f24
commit a67a72c17c
1 changed files with 119 additions and 92 deletions

View File

@ -348,7 +348,6 @@ to form an empty sum.
Otherwise we calculate the sum of all values Otherwise we calculate the sum of all values
of the form $\texttt{solve}(x-c)$ where $c$ is in \texttt{coins}. of the form $\texttt{solve}(x-c)$ where $c$ is in \texttt{coins}.
The following code constructs an array The following code constructs an array
$\texttt{count}$ such that $\texttt{count}$ such that
$\texttt{count}[x]$ equals $\texttt{count}[x]$ equals
@ -393,15 +392,13 @@ possibilities of dynamic programming.
\index{longest increasing subsequence} \index{longest increasing subsequence}
Let us consider the following problem: Our first problem is to find the
Given an array that contains $n$
numbers,
our task is to find the
\key{longest increasing subsequence} \key{longest increasing subsequence}
of the array. in an array \texttt{t} of $n$ elements.
This is a sequence of array elements This is a maximum-length
sequence of array elements
that goes from left to right, that goes from left to right,
and each element of the sequence is larger and each element in the sequence is larger
than the previous element. than the previous element.
For example, in the array For example, in the array
@ -462,65 +459,81 @@ contains 4 elements:
\end{tikzpicture} \end{tikzpicture}
\end{center} \end{center}
Let $f(k)$ be the length of the Let $\texttt{length}(k)$ denote
the length of the
longest increasing subsequence longest increasing subsequence
that ends at position $k$. that ends at position $k$.
Using this function, the answer to the problem Thus, if we calculate all values of
is the largest of the values $\texttt{length}(k)$ where $0 \le k \le n-1$,
$f(0),f(1),\ldots,f(n-1)$. we will find out the length of the
For example, in the above array longest increasing subsequence.
the values of the function are as follows: For example, the values of the function
for the above array are as follows:
\[ \[
\begin{array}{lcl} \begin{array}{lcl}
f(0) & = & 1 \\ \texttt{length}(0) & = & 1 \\
f(1) & = & 1 \\ \texttt{length}(1) & = & 1 \\
f(2) & = & 2 \\ \texttt{length}(2) & = & 2 \\
f(3) & = & 1 \\ \texttt{length}(3) & = & 1 \\
f(4) & = & 3 \\ \texttt{length}(4) & = & 3 \\
f(5) & = & 2 \\ \texttt{length}(5) & = & 2 \\
f(6) & = & 4 \\ \texttt{length}(6) & = & 4 \\
f(7) & = & 2 \\ \texttt{length}(7) & = & 2 \\
\end{array} \end{array}
\] \]
When calculating the value of $f(k)$, For example, $\texttt{length}(6)=4$,
there are two possibilities how the subsequence because the longest increasing subsequence
that ends at position $k$ is constructed: that ends at position 6 consists of 4 elements.
\begin{enumerate}
\item The subsequence
only contains the element at position $k$. In this case $f(k)=1$.
\item The subsequence contains a subsequence
that ends at position $i$ where $i<k$,
followed by the element at position $k$.
The element at position $i$ must be smaller
than the element at position $k$.
In this case $f(k)=f(i)+1$.
\end{enumerate}
For example, in the above example $f(6)=4$, To calculate a value of $\texttt{length}(k)$,
because the subsequence $[2,5,7]$ of length 3 we should find a position $i<k$
ends at position 4, and by adding the element for which $\texttt{t}[i]<\texttt{t}[k]$
at position 6 to this subsequence, and $\texttt{length}(i)$ is as large as possible.
we get the optimal subsequence $[2,5,7,8]$ of length 4. Then we know that
$\texttt{length}(k)=\texttt{length}(i)+1$,
because this is an optimal way to add
$\texttt{t}[k]$ to a subsequence.
However, if there is no such position $i$,
then $\texttt{length}(k)=1$,
which means that the subsequence only contains
$\texttt{t}[k]$.
An easy way to calculate the Since all values of the function can be calculated
value of $f(k)$ is to from its smaller values,
go through all previous values we can use dynamic programming.
$f(0),f(1),\ldots,f(k-1)$ and select the best solution. In the following code, the values
The time complexity of such an algorithm is $O(n^2)$. of the function will be stored in an array
Surprisingly, it is also possible to solve the $\texttt{length}$.
problem in $O(n \log n)$ time. Can you see how?
\begin{lstlisting}
for (int k = 0; k < n; k++) {
length[k] = 1;
for (int i = 0; i < k; i++) {
if (t[i] < t[k]) {
length[k] = max(length[k],length[i]+1);
}
}
}
\end{lstlisting}
This code works in $O(n^2)$ time,
because it consists of two nested loops.
However, it is also possible to implement
the dynamic programming calculation
more efficiently in $O(n \log n)$ time.
Can you find a way to do this?
\section{Paths in a grid} \section{Paths in a grid}
Our next problem is to find a path Our next problem is to find a path
in an $n \times n$ grid
from the upper-left corner to from the upper-left corner to
the lower-right corner such that the lower-right corner
of an $n \times n$ grid, such that
we only move down and right. we only move down and right.
Each square contains a number, Each square contains a value,
and the path should be constructed so and the path should be constructed so
that the sum of the numbers along that the sum of the values along
the path is as large as possible. the path is as large as possible.
The following picture shows an optimal The following picture shows an optimal
@ -566,19 +579,29 @@ path in a grid:
\end{scope} \end{scope}
\end{tikzpicture} \end{tikzpicture}
\end{center} \end{center}
The sum of the numbers on the path is 67, The sum of the values on the path is 67,
and this is the largest possible sum on a path and this is the largest possible sum on a path
from the from the
upper-left corner to the lower-right corner. upper-left corner to the lower-right corner.
We can approach the problem by Assume that the rows and columns of the
calculating for each square $(y,x)$ grid are numbered from 1 to $n$,
the maximum sum on a path and $\texttt{value}[y][x]$ equals the value
from the upper-left corner to square $(y,x)$. of square $(y,x)$.
Let $f(y,x)$ denote this sum, Let $\texttt{sum}(y,x)$ denote the maximum
so $f(n,n)$ is the maximum sum on a path sum on a path from the upper-left corner
to square $(y,x)$.
Now $\texttt{sum}(n,n)$ tells us
the maximum sum
from the upper-left corner to from the upper-left corner to
the lower-right corner. the lower-right corner.
For example, in the above grid,
$\texttt{sum}(5,5)=67$.
We can recursively calculate the sums
as follows:
\[ \texttt{sum}(y,x) = \max(\texttt{sum}(y,x-1),\texttt{sum}(y-1,x))+\texttt{value}[y][x]\]
The recursive formula is based on the observation The recursive formula is based on the observation
that a path that ends at square $(y,x)$ that a path that ends at square $(y,x)$
@ -597,27 +620,31 @@ or square $(y-1,x)$:
\end{tikzpicture} \end{tikzpicture}
\end{center} \end{center}
Let $r(y,x)$ denote the number in square $(y,x)$. Thus, we select the direction that maximizes
The base cases for the recursive function the sum.
are as follows: We assume that $\texttt{sum}(y,x)=0$
if $y=0$ or $x=0$ (because no such paths exist),
so the recursive formula also works when $y=1$ or $x=1$.
\[ Since the function \texttt{sum} has two parameters,
\begin{array}{lcl} the dynamic programming array also has two dimensions.
f(1,1) & = & r(1,1) \\ For example, we can use an array
f(1,x) & = & f(1,x-1)+r(1,x) \\ \begin{lstlisting}
f(y,1) & = & f(y-1,1)+r(y,1)\\ int sum[N][N];
\end{array} \end{lstlisting}
\] and calculate the sums as follows:
\begin{lstlisting}
for (int y = 1; y <= n; y++) {
for (int x = 1; x <= n; x++) {
sum[y][x] = max(sum[y][x-1],sum[y-1][x])+value[y][x];
}
}
\end{lstlisting}
In the general case there are two Note that it is not needed to separately handle the
possible paths, and we should select the path cases where $y=1$ or $x=1$, because we use a
that produces the larger sum: one-indexed array whose values are initially zeros.
\[ f(y,x) = \max(f(y,x-1),f(y-1,x))+r(y,x)\] The time complexity of the algorithm is $O(n^2)$.
The time complexity of the solution is $O(n^2)$,
because each value $f(y,x)$ can be calculated
in constant time using the values of the
adjacent squares.
\section{Knapsack} \section{Knapsack}
@ -625,10 +652,10 @@ adjacent squares.
\key{Knapsack} is a classic problem where we \key{Knapsack} is a classic problem where we
are given $n$ objects with weights are given $n$ objects with weights
$p_1,p_2,\ldots,p_n$ and values $w_1,w_2,\ldots,w_n$ and values
$a_1,a_2,\ldots,a_n$. $v_1,v_2,\ldots,v_n$.
Our task is to choose a subset of the objects Our task is to choose a subset of the objects
such that the sum of the weights is at most $x$ such that the sum of the weights is at most $W$
and the sum of the values is as large as possible. and the sum of the values is as large as possible.
\begin{samepage} \begin{samepage}
@ -644,26 +671,26 @@ D & 5 & 3 \\
\end{tabular} \end{tabular}
\end{center} \end{center}
\end{samepage} \end{samepage}
and the maximum allowed total weight is 12, and $W=12$,
an optimal solution is to select objects $B$ and $D$. an optimal solution is to select objects $B$ and $D$.
Their total weight $6+5=11$ does not exceed 12, In this case, the sum of weights is
and their total value $3+3=6$ is the largest possible. $6+5=11 \le 12$, and the sum of values is $3+3=6$.
This task can be solved in two different ways This problem can be solved in two different ways
using dynamic programming. using dynamic programming.
We can either regard the problem as maximizing the We can either regard the problem as maximizing the
total value of the objects or total value of the objects or
minimizing the total weight of the objects. as minimizing the total weight of the objects.
\subsubsection{Solution 1} \subsubsection{Solution 1}
\textit{Maximization:} Let $f(k,u)$ \textit{Maximization:} Let $\texttt{value}(k,u)$
denote the largest possible total value denote the maximum value
when a subset of objects $1 \ldots k$ is selected of a subset of objects $1 \ldots k$
such that the total weight is $u$. whose weight is $u$.
The solution to the problem is Thus, the solution to the problem is
the largest value \[\max_{0 \le u \le W} \texttt{value}(n,u).\]
$f(n,u)$ where $0 \le u \le x$.
A recursive formula for calculating A recursive formula for calculating
the function is the function is
\[f(k,u) = \max(f(k-1,u),f(k-1,u-p_k)+a_k),\] \[f(k,u) = \max(f(k-1,u),f(k-1,u-p_k)+a_k),\]