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