Corrections
This commit is contained in:
parent
3dd874a4fa
commit
3f31020076
46
luku05.tex
46
luku05.tex
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
\key{Complete search}
|
\key{Complete search}
|
||||||
is a general method that can be used
|
is a general method that can be used
|
||||||
for solving almost any algorithm problem.
|
to solve almost any algorithm problem.
|
||||||
The idea is to generate all possible
|
The idea is to generate all possible
|
||||||
solutions to the problem using brute force,
|
solutions to the problem using brute force,
|
||||||
and then select the best solution or count the
|
and then select the best solution or count the
|
||||||
|
@ -30,7 +30,7 @@ or use bit operations of integers.
|
||||||
|
|
||||||
An elegant way to go through all subsets
|
An elegant way to go through all subsets
|
||||||
of a set is to use recursion.
|
of a set is to use recursion.
|
||||||
The following function \texttt{gen}
|
The following function
|
||||||
generates the subsets of the set
|
generates the subsets of the set
|
||||||
$\{1,2,\ldots,n\}$.
|
$\{1,2,\ldots,n\}$.
|
||||||
The function maintains a vector
|
The function maintains a vector
|
||||||
|
@ -128,8 +128,8 @@ which corresponds to an integer between $0 \ldots 2^n-1$.
|
||||||
The ones in the bit sequence indicate
|
The ones in the bit sequence indicate
|
||||||
which elements are included in the subset.
|
which elements are included in the subset.
|
||||||
|
|
||||||
The usual convention is that element $k$
|
The usual convention is that the $k$th element
|
||||||
is included in the subset if the $k$th last bit
|
is included in the subset exactly when the $k$th last bit
|
||||||
in the sequence is one.
|
in the sequence is one.
|
||||||
For example, the bit representation of 25
|
For example, the bit representation of 25
|
||||||
is 11001, that corresponds to the subset $\{1,4,5\}$.
|
is 11001, that corresponds to the subset $\{1,4,5\}$.
|
||||||
|
@ -143,8 +143,8 @@ for (int b = 0; b < (1<<n); b++) {
|
||||||
}
|
}
|
||||||
\end{lstlisting}
|
\end{lstlisting}
|
||||||
|
|
||||||
The following code shows how we can derive
|
The following code shows how we can find
|
||||||
the elements in a subset from the bit sequence.
|
the elements of a subset that corresponds to a bit sequence.
|
||||||
When processing each subset,
|
When processing each subset,
|
||||||
the code builds a vector that contains the
|
the code builds a vector that contains the
|
||||||
elements in the subset.
|
elements in the subset.
|
||||||
|
@ -165,14 +165,14 @@ for (int b = 0; b < (1<<n); b++) {
|
||||||
Next we will consider the problem of generating
|
Next we will consider the problem of generating
|
||||||
all permutations of a set of $n$ elements.
|
all permutations of a set of $n$ elements.
|
||||||
Again, there are two approaches:
|
Again, there are two approaches:
|
||||||
we can either use recursion or go trough the
|
we can either use recursion or go through the
|
||||||
permutations iteratively.
|
permutations iteratively.
|
||||||
|
|
||||||
\subsubsection{Method 1}
|
\subsubsection{Method 1}
|
||||||
|
|
||||||
Like subsets, permutations can be generated
|
Like subsets, permutations can be generated
|
||||||
using recursion.
|
using recursion.
|
||||||
The following function \texttt{gen} goes
|
The following function goes
|
||||||
through the permutations of the set $\{1,2,\ldots,n\}$.
|
through the permutations of the set $\{1,2,\ldots,n\}$.
|
||||||
The function builds a vector that contains
|
The function builds a vector that contains
|
||||||
the elements in the permutation,
|
the elements in the permutation,
|
||||||
|
@ -180,7 +180,7 @@ and the search begins when the function is
|
||||||
called without parameters.
|
called without parameters.
|
||||||
|
|
||||||
\begin{lstlisting}
|
\begin{lstlisting}
|
||||||
void haku() {
|
void gen() {
|
||||||
if (v.size() == n) {
|
if (v.size() == n) {
|
||||||
// process permutation v
|
// process permutation v
|
||||||
} else {
|
} else {
|
||||||
|
@ -188,7 +188,7 @@ void haku() {
|
||||||
if (p[i]) continue;
|
if (p[i]) continue;
|
||||||
p[i] = 1;
|
p[i] = 1;
|
||||||
v.push_back(i);
|
v.push_back(i);
|
||||||
haku();
|
gen();
|
||||||
p[i] = 0;
|
p[i] = 0;
|
||||||
v.pop_back();
|
v.pop_back();
|
||||||
}
|
}
|
||||||
|
@ -275,8 +275,9 @@ any of the queens placed before.
|
||||||
A solution has been found when all
|
A solution has been found when all
|
||||||
$n$ queens have been placed to the board.
|
$n$ queens have been placed to the board.
|
||||||
|
|
||||||
For example, when $n=4$, the backtracking
|
For example, when $n=4$,
|
||||||
algorithm generates the following tree:
|
some partial solutions generated by
|
||||||
|
the backtracking algorithm are as follows:
|
||||||
|
|
||||||
\begin{center}
|
\begin{center}
|
||||||
\begin{tikzpicture}[scale=.55]
|
\begin{tikzpicture}[scale=.55]
|
||||||
|
@ -436,7 +437,7 @@ the $4 \times 4$ board are numbered as follows:
|
||||||
\end{center}
|
\end{center}
|
||||||
|
|
||||||
The above backtracking
|
The above backtracking
|
||||||
algorithm shows that
|
algorithm tells us that
|
||||||
there are 92 ways to place 8
|
there are 92 ways to place 8
|
||||||
queens to the $8 \times 8$ chessboard.
|
queens to the $8 \times 8$ chessboard.
|
||||||
When $n$ increases, the search quickly becomes slow,
|
When $n$ increases, the search quickly becomes slow,
|
||||||
|
@ -453,7 +454,7 @@ on a modern computer
|
||||||
We can often optimize backtracking
|
We can often optimize backtracking
|
||||||
by pruning the search tree.
|
by pruning the search tree.
|
||||||
The idea is to add ''intelligence'' to the algorithm
|
The idea is to add ''intelligence'' to the algorithm
|
||||||
so that it will realize as soon as possible
|
so that it will notice as soon as possible
|
||||||
if a partial solution cannot be extended
|
if a partial solution cannot be extended
|
||||||
to a complete solution.
|
to a complete solution.
|
||||||
Such optimizations can have a tremendous
|
Such optimizations can have a tremendous
|
||||||
|
@ -484,7 +485,8 @@ One of the paths is as follows:
|
||||||
\end{tikzpicture}
|
\end{tikzpicture}
|
||||||
\end{center}
|
\end{center}
|
||||||
|
|
||||||
Next we will concentrate on the $7 \times 7$ case.
|
We will concentrate on the $7 \times 7$ case,
|
||||||
|
because its level of difficulty is appropriate to our needs.
|
||||||
We begin with a straightforward backtracking algorithm,
|
We begin with a straightforward backtracking algorithm,
|
||||||
and then optimize it step by step using observations
|
and then optimize it step by step using observations
|
||||||
how the search can be pruned.
|
how the search can be pruned.
|
||||||
|
@ -509,7 +511,7 @@ recursive calls: 76 billions
|
||||||
|
|
||||||
\subsubsection{Optimization 1}
|
\subsubsection{Optimization 1}
|
||||||
|
|
||||||
In any solution, we first move a step
|
In any solution, we first move one step
|
||||||
down or right.
|
down or right.
|
||||||
There are always two paths that
|
There are always two paths that
|
||||||
are symmetric
|
are symmetric
|
||||||
|
@ -551,7 +553,7 @@ For example, the following paths are symmetric:
|
||||||
\end{center}
|
\end{center}
|
||||||
|
|
||||||
Hence, we can decide that we always first
|
Hence, we can decide that we always first
|
||||||
move down,
|
move one step down,
|
||||||
and finally multiply the number of the solutions by two.
|
and finally multiply the number of the solutions by two.
|
||||||
|
|
||||||
\begin{itemize}
|
\begin{itemize}
|
||||||
|
@ -683,9 +685,9 @@ i.e., at the top of the search tree.
|
||||||
|
|
||||||
\key{Meet in the middle} is a technique
|
\key{Meet in the middle} is a technique
|
||||||
where the search space is divided into
|
where the search space is divided into
|
||||||
two equally large parts.
|
two parts of about equal size.
|
||||||
A separate search is performed
|
A separate search is performed
|
||||||
for each of the parts,
|
for both of the parts,
|
||||||
and finally the results of the searches are combined.
|
and finally the results of the searches are combined.
|
||||||
|
|
||||||
The technique can be used
|
The technique can be used
|
||||||
|
@ -727,8 +729,8 @@ to a list $S_A$.
|
||||||
Correspondingly, the second search creates
|
Correspondingly, the second search creates
|
||||||
a list $S_B$ from $B$.
|
a list $S_B$ from $B$.
|
||||||
After this, it suffices to check if it is possible
|
After this, it suffices to check if it is possible
|
||||||
to choose one number from $S_A$ and another
|
to choose one element from $S_A$ and another
|
||||||
number from $S_B$ so that their sum is $x$.
|
element from $S_B$ so that their sum is $x$.
|
||||||
This is possible exactly when there is a way to
|
This is possible exactly when there is a way to
|
||||||
form the sum $x$ using the numbers in the original list.
|
form the sum $x$ using the numbers in the original list.
|
||||||
|
|
||||||
|
@ -736,7 +738,7 @@ For example, suppose that the list is $[2,4,5,9]$ and $x=15$.
|
||||||
First, we divide the list into $A=[2,4]$ and $B=[5,9]$.
|
First, we divide the list into $A=[2,4]$ and $B=[5,9]$.
|
||||||
After this, we create lists
|
After this, we create lists
|
||||||
$S_A=[0,2,4,6]$ and $S_B=[0,5,9,14]$.
|
$S_A=[0,2,4,6]$ and $S_B=[0,5,9,14]$.
|
||||||
In this case, the sum $x=15$ is possible to form
|
In this case, the sum $x=15$ is possible to form,
|
||||||
because we can choose the number $6$ from $S_A$
|
because we can choose the number $6$ from $S_A$
|
||||||
and the number $9$ from $S_B$,
|
and the number $9$ from $S_B$,
|
||||||
which corresponds to the solution $[2,4,9]$.
|
which corresponds to the solution $[2,4,9]$.
|
||||||
|
|
30
luku06.tex
30
luku06.tex
|
@ -12,8 +12,8 @@ the final solution.
|
||||||
For this reason, greedy algorithms
|
For this reason, greedy algorithms
|
||||||
are usually very efficient.
|
are usually very efficient.
|
||||||
|
|
||||||
The difficulty in designing a greedy algorithm
|
The difficulty in designing greedy algorithms
|
||||||
is to invent a greedy strategy
|
is to find a greedy strategy
|
||||||
that always produces an optimal solution
|
that always produces an optimal solution
|
||||||
to the problem.
|
to the problem.
|
||||||
The locally optimal choices in a greedy
|
The locally optimal choices in a greedy
|
||||||
|
@ -32,7 +32,7 @@ $\{c_1,c_2,\ldots,c_k\}$,
|
||||||
and each coin can be used as many times we want.
|
and each coin can be used as many times we want.
|
||||||
What is the minimum number of coins needed?
|
What is the minimum number of coins needed?
|
||||||
|
|
||||||
For example, if the coins are euro coins (in cents)
|
For example, if the coins are the euro coins (in cents)
|
||||||
\[\{1,2,5,10,20,50,100,200\}\]
|
\[\{1,2,5,10,20,50,100,200\}\]
|
||||||
and the sum of money is 520,
|
and the sum of money is 520,
|
||||||
we need at least four coins.
|
we need at least four coins.
|
||||||
|
@ -71,13 +71,13 @@ because we could replace
|
||||||
coins $2+2+2$ by coins $5+1$ and
|
coins $2+2+2$ by coins $5+1$ and
|
||||||
coins $20+20+20$ by coins $50+10$.
|
coins $20+20+20$ by coins $50+10$.
|
||||||
Moreover, an optimal solution cannot contain
|
Moreover, an optimal solution cannot contain
|
||||||
coins $2+2+1$ or $20+20+10$
|
coins $2+2+1$ or $20+20+10$,
|
||||||
because we could replace them by coins $5$ and $50$.
|
because we could replace them by coins $5$ and $50$.
|
||||||
|
|
||||||
Using these observations,
|
Using these observations,
|
||||||
we can show for each coin $x$ that
|
we can show for each coin $x$ that
|
||||||
it is not possible to optimally construct
|
it is not possible to optimally construct
|
||||||
sum $x$ or any larger sum by only using coins
|
a sum $x$ or any larger sum by only using coins
|
||||||
that are smaller than $x$.
|
that are smaller than $x$.
|
||||||
For example, if $x=100$, the largest optimal
|
For example, if $x=100$, the largest optimal
|
||||||
sum using the smaller coins is $50+20+20+5+2+2=99$.
|
sum using the smaller coins is $50+20+20+5+2+2=99$.
|
||||||
|
@ -113,10 +113,10 @@ correct answer.
|
||||||
\section{Scheduling}
|
\section{Scheduling}
|
||||||
|
|
||||||
Many scheduling problems can be solved
|
Many scheduling problems can be solved
|
||||||
using a greedy strategy.
|
using greedy algorithms.
|
||||||
A classic problem is as follows:
|
A classic problem is as follows:
|
||||||
Given $n$ events with their starting and ending
|
Given $n$ events with their starting and ending
|
||||||
times, we should plan a schedule
|
times, our goal is to plan a schedule
|
||||||
that includes as many events as possible.
|
that includes as many events as possible.
|
||||||
It is not possible to select an event partially.
|
It is not possible to select an event partially.
|
||||||
For example, consider the following events:
|
For example, consider the following events:
|
||||||
|
@ -172,7 +172,7 @@ selects the following events:
|
||||||
\end{tikzpicture}
|
\end{tikzpicture}
|
||||||
\end{center}
|
\end{center}
|
||||||
|
|
||||||
However, select short events is not always
|
However, selecting short events is not always
|
||||||
a correct strategy, but the algorithm fails,
|
a correct strategy, but the algorithm fails,
|
||||||
for example, in the following case:
|
for example, in the following case:
|
||||||
\begin{center}
|
\begin{center}
|
||||||
|
@ -269,9 +269,9 @@ and the greedy algorithm is correct.
|
||||||
\section{Tasks and deadlines}
|
\section{Tasks and deadlines}
|
||||||
|
|
||||||
Let us now consider a problem where
|
Let us now consider a problem where
|
||||||
we are given $n$ tasks with durations and deadlines,
|
we are given $n$ tasks with durations and deadlines
|
||||||
and our task is to choose an order to perform the tasks.
|
and our task is to choose an order to perform the tasks.
|
||||||
For each task, we get $d-x$ points
|
For each task, we earn $d-x$ points
|
||||||
where $d$ is the task's deadline
|
where $d$ is the task's deadline
|
||||||
and $x$ is the moment when we finished the task.
|
and $x$ is the moment when we finished the task.
|
||||||
What is the largest possible total score
|
What is the largest possible total score
|
||||||
|
@ -367,7 +367,7 @@ Here $a>b$, so we should swap the tasks:
|
||||||
\end{scope}
|
\end{scope}
|
||||||
\end{tikzpicture}
|
\end{tikzpicture}
|
||||||
\end{center}
|
\end{center}
|
||||||
Now $X$ gives $b$ points less and $Y$ gives $a$ points more,
|
Now $X$ gives $b$ points fewer and $Y$ gives $a$ points more,
|
||||||
so the total score increases by $a-b > 0$.
|
so the total score increases by $a-b > 0$.
|
||||||
In an optimal solution,
|
In an optimal solution,
|
||||||
for any two consecutive tasks,
|
for any two consecutive tasks,
|
||||||
|
@ -470,7 +470,7 @@ which means that the length of each
|
||||||
codeword is the same.
|
codeword is the same.
|
||||||
For example, we can compress the string
|
For example, we can compress the string
|
||||||
\texttt{AABACDACA} as follows:
|
\texttt{AABACDACA} as follows:
|
||||||
\[000001001011001000\]
|
\[00\,00\,01\,00\,10\,11\,00\,10\,00\]
|
||||||
Using this code, the length of the compressed
|
Using this code, the length of the compressed
|
||||||
string is 18 bits.
|
string is 18 bits.
|
||||||
However, we can compress the string better
|
However, we can compress the string better
|
||||||
|
@ -496,7 +496,7 @@ An optimal code produces a compressed string
|
||||||
that is as short as possible.
|
that is as short as possible.
|
||||||
In this case, the compressed string using
|
In this case, the compressed string using
|
||||||
the optimal code is
|
the optimal code is
|
||||||
\[001100101110100,\]
|
\[0\,0\,110\,0\,10\,111\,0\,10\,0,\]
|
||||||
so only 15 bits are needed instead of 18 bits.
|
so only 15 bits are needed instead of 18 bits.
|
||||||
Thus, thanks to a better code it was possible to
|
Thus, thanks to a better code it was possible to
|
||||||
save 3 bits in the compressed string.
|
save 3 bits in the compressed string.
|
||||||
|
@ -539,12 +539,12 @@ in the string,
|
||||||
and each character's codeword can be read
|
and each character's codeword can be read
|
||||||
by following a path from the root to
|
by following a path from the root to
|
||||||
the corresponding node.
|
the corresponding node.
|
||||||
A move to the left correspons to bit 0,
|
A move to the left corresponds to bit 0,
|
||||||
and a move to the right corresponds to bit 1.
|
and a move to the right corresponds to bit 1.
|
||||||
|
|
||||||
Initially, each character of the string is
|
Initially, each character of the string is
|
||||||
represented by a node whose weight is the
|
represented by a node whose weight is the
|
||||||
number of times the character appears in the string.
|
number of times the character occurs in the string.
|
||||||
Then at each step two nodes with minimum weights
|
Then at each step two nodes with minimum weights
|
||||||
are combined by creating
|
are combined by creating
|
||||||
a new node whose weight is the sum of the weights
|
a new node whose weight is the sum of the weights
|
||||||
|
|
97
luku07.tex
97
luku07.tex
|
@ -14,7 +14,7 @@ There are two uses for dynamic programming:
|
||||||
|
|
||||||
\begin{itemize}
|
\begin{itemize}
|
||||||
\item
|
\item
|
||||||
\key{Findind an optimal solution}:
|
\key{Finding an optimal solution}:
|
||||||
We want to find a solution that is
|
We want to find a solution that is
|
||||||
as large as possible or as small as possible.
|
as large as possible or as small as possible.
|
||||||
\item
|
\item
|
||||||
|
@ -24,14 +24,14 @@ possible solutions.
|
||||||
\end{itemize}
|
\end{itemize}
|
||||||
|
|
||||||
We will first see how dynamic programming can
|
We will first see how dynamic programming can
|
||||||
be used for finding an optimal solution,
|
be used to find an optimal solution,
|
||||||
and then we will use the same idea for
|
and then we will use the same idea for
|
||||||
counting the solutions.
|
counting the solutions.
|
||||||
|
|
||||||
Understanding dynamic programming is a milestone
|
Understanding dynamic programming is a milestone
|
||||||
in every competitive programmer's career.
|
in every competitive programmer's career.
|
||||||
While the basic idea of the technique is simple,
|
While the basic idea of the technique is simple,
|
||||||
the challenge is how to apply it for different problems.
|
the challenge is how to apply it to different problems.
|
||||||
This chapter introduces a set of classic problems
|
This chapter introduces a set of classic problems
|
||||||
that are a good starting point.
|
that are a good starting point.
|
||||||
|
|
||||||
|
@ -47,7 +47,7 @@ In Chapter 6, we solved the problem using a
|
||||||
greedy algorithm that always selects the largest
|
greedy algorithm that always selects the largest
|
||||||
possible coin.
|
possible coin.
|
||||||
The greedy algorithm works, for example,
|
The greedy algorithm works, for example,
|
||||||
when coins are euro coins,
|
when the coins are the euro coins,
|
||||||
but in the general case the greedy algorithm
|
but in the general case the greedy algorithm
|
||||||
does not necessarily produce an optimal solution.
|
does not necessarily produce an optimal solution.
|
||||||
|
|
||||||
|
@ -60,15 +60,15 @@ that goes through all possibilities how to
|
||||||
form the sum, like a brute force algorithm.
|
form the sum, like a brute force algorithm.
|
||||||
However, the dynamic programming
|
However, the dynamic programming
|
||||||
algorithm is efficient because
|
algorithm is efficient because
|
||||||
it uses \emph{memoization} to
|
it uses \emph{memoization} and
|
||||||
calculate the answer to each subproblem only once.
|
calculates the answer to each subproblem only once.
|
||||||
|
|
||||||
\subsubsection{Recursive formulation}
|
\subsubsection{Recursive formulation}
|
||||||
|
|
||||||
The idea in dynamic programming is to
|
The idea in dynamic programming is to
|
||||||
formulate the problem recursively so
|
formulate the problem recursively so
|
||||||
that the answer to the problem can be
|
that the answer to the problem can be
|
||||||
calculated from the answers for smaller
|
calculated from answers to smaller
|
||||||
subproblems.
|
subproblems.
|
||||||
In the coin problem, a natural recursive
|
In the coin problem, a natural recursive
|
||||||
problem is as follows:
|
problem is as follows:
|
||||||
|
@ -107,8 +107,8 @@ and $f(5)=2$ because the sum 5 can
|
||||||
be formed using coins 1 and 4.
|
be formed using coins 1 and 4.
|
||||||
|
|
||||||
The essential property in the function is
|
The essential property in the function is
|
||||||
that the value $f(x)$ can be calculated
|
that each value of $f(x)$ can be calculated
|
||||||
recursively from the smaller values of the function.
|
recursively from smaller values of the function.
|
||||||
For example, if the coin set is $\{1,3,4\}$,
|
For example, if the coin set is $\{1,3,4\}$,
|
||||||
there are three ways to select the first coin
|
there are three ways to select the first coin
|
||||||
in a solution: we can choose coin 1, 3 or 4.
|
in a solution: we can choose coin 1, 3 or 4.
|
||||||
|
@ -133,9 +133,8 @@ In addition, it is convenient to define
|
||||||
\[f(x)=\infty\hspace{8px}\textrm{if $x<0$}.\]
|
\[f(x)=\infty\hspace{8px}\textrm{if $x<0$}.\]
|
||||||
This means that an infinite number of coins
|
This means that an infinite number of coins
|
||||||
is needed for forming a negative sum of money.
|
is needed for forming a negative sum of money.
|
||||||
This prevents the situation that the recursive
|
This prevents the function from constructing
|
||||||
function would form a solution where the
|
a solution where the initial sum of money is negative.
|
||||||
initial sum of money is negative.
|
|
||||||
|
|
||||||
Once a recursive function that solves the problem
|
Once a recursive function that solves the problem
|
||||||
has been found,
|
has been found,
|
||||||
|
@ -159,7 +158,7 @@ and the value $10^9$ denotes infinity.
|
||||||
This function works but it is not efficient yet,
|
This function works but it is not efficient yet,
|
||||||
because it goes through a large number
|
because it goes through a large number
|
||||||
of ways to construct the sum.
|
of ways to construct the sum.
|
||||||
However, the function becomes efficient by
|
However, the function can be made efficient by
|
||||||
using memoization.
|
using memoization.
|
||||||
|
|
||||||
\subsubsection{Memoization}
|
\subsubsection{Memoization}
|
||||||
|
@ -170,20 +169,20 @@ Dynamic programming allows us to calculate the
|
||||||
value of a recursive function efficiently
|
value of a recursive function efficiently
|
||||||
using \key{memoization}.
|
using \key{memoization}.
|
||||||
This means that an auxiliary array is used
|
This means that an auxiliary array is used
|
||||||
for storing the values of the function
|
for recording the values of the function
|
||||||
for different parameters.
|
for different parameters.
|
||||||
For each parameter, the value of the function
|
For each parameter, the value of the function
|
||||||
is calculated recursively only once, and after this,
|
is calculated recursively only once, and after this,
|
||||||
the value can be directly retrieved from the array.
|
the value can be directly retrieved from the array.
|
||||||
|
|
||||||
In this problem, we can use the array
|
In this problem, we can use an array
|
||||||
\begin{lstlisting}
|
\begin{lstlisting}
|
||||||
int d[N];
|
int d[N];
|
||||||
\end{lstlisting}
|
\end{lstlisting}
|
||||||
|
|
||||||
where $\texttt{d}[x]$ will contain
|
where $\texttt{d}[x]$ will contain
|
||||||
the value $f(x)$.
|
the value of $f(x)$.
|
||||||
The constant $N$ should be chosen so
|
The constant $N$ has to be chosen so
|
||||||
that all required values of the function fit
|
that all required values of the function fit
|
||||||
in the array.
|
in the array.
|
||||||
|
|
||||||
|
@ -208,23 +207,23 @@ The function handles the base cases
|
||||||
$x=0$ and $x<0$ as previously.
|
$x=0$ and $x<0$ as previously.
|
||||||
Then the function checks if
|
Then the function checks if
|
||||||
$f(x)$ has already been calculated
|
$f(x)$ has already been calculated
|
||||||
and stored in $\texttt{d}[x]$.
|
in $\texttt{d}[x]$.
|
||||||
If $f(x)$ is found in the array,
|
If the value of $f(x)$ is found in the array,
|
||||||
the function directly returns it.
|
the function directly returns it.
|
||||||
Otherwise the function calculates the value
|
Otherwise the function calculates the value
|
||||||
recursively and stores it in $\texttt{d}[x]$.
|
recursively and stores it in $\texttt{d}[x]$.
|
||||||
|
|
||||||
Using memoization the function works
|
Using memoization the function works
|
||||||
efficiently, because the answer for each $x$
|
efficiently, because the answer for each parameter $x$
|
||||||
is calculated recursively only once.
|
is calculated recursively only once.
|
||||||
After a value of $f(x)$ has been stored in the array,
|
After a value of $f(x)$ has been stored in the array,
|
||||||
it can be efficiently retrieved whenever the
|
it can be efficiently retrieved whenever the
|
||||||
function will be called again with parameter $x$.
|
function will be called again with the parameter $x$.
|
||||||
|
|
||||||
The time complexity of the resulting algorithm
|
The time complexity of the resulting algorithm
|
||||||
is $O(xk)$ where the sum is $x$ and the number of
|
is $O(xk)$ where the sum is $x$ and the number of
|
||||||
coins is $k$.
|
coins is $k$.
|
||||||
In practice, the algorithm is usable if
|
In practice, the algorithm can be used if
|
||||||
$x$ is so small that it is possible to allocate
|
$x$ is so small that it is possible to allocate
|
||||||
an array for all possible function parameters.
|
an array for all possible function parameters.
|
||||||
|
|
||||||
|
@ -294,7 +293,7 @@ while (x > 0) {
|
||||||
|
|
||||||
\subsubsection{Counting the number of solutions}
|
\subsubsection{Counting the number of solutions}
|
||||||
|
|
||||||
Let us now consider a variation of the problem
|
Let us now consider a variant of the problem
|
||||||
that is otherwise like the original problem,
|
that is otherwise like the original problem,
|
||||||
but we should count the total number of solutions instead
|
but we should count the total number of solutions instead
|
||||||
of finding the optimal solution.
|
of finding the optimal solution.
|
||||||
|
@ -319,7 +318,7 @@ The difference is that when finding the optimal solution,
|
||||||
we maximize or minimize something in the recursion,
|
we maximize or minimize something in the recursion,
|
||||||
but now we will calculate sums of numbers of solutions.
|
but now we will calculate sums of numbers of solutions.
|
||||||
|
|
||||||
In the coin problem, we can define a function $f(x)$
|
To solve the problem, we can define a function $f(x)$
|
||||||
that returns the number of ways to construct
|
that returns the number of ways to construct
|
||||||
the sum $x$ using the coins.
|
the sum $x$ using the coins.
|
||||||
For example, $f(5)=6$ when the coins are $\{1,3,4\}$.
|
For example, $f(5)=6$ when the coins are $\{1,3,4\}$.
|
||||||
|
@ -330,7 +329,7 @@ because to form the sum $x$, we have to first
|
||||||
choose some coin $c_i$ and then form the sum $x-c_i$.
|
choose some coin $c_i$ and then form the sum $x-c_i$.
|
||||||
The base cases are $f(0)=1$, because there is exactly
|
The base cases are $f(0)=1$, because there is exactly
|
||||||
one way to form the sum 0 using an empty set of coins,
|
one way to form the sum 0 using an empty set of coins,
|
||||||
and $f(x)=0$, when $x<0$, because it's not possible
|
and $f(x)=0$, when $x<0$, because it is not possible
|
||||||
to form a negative sum of money.
|
to form a negative sum of money.
|
||||||
|
|
||||||
If the coin set is $\{1,3,4\}$, the function is
|
If the coin set is $\{1,3,4\}$, the function is
|
||||||
|
@ -370,8 +369,8 @@ that it is not required to calculate the exact number
|
||||||
but it is enough to give the answer modulo $m$
|
but it is enough to give the answer modulo $m$
|
||||||
where, for example, $m=10^9+7$.
|
where, for example, $m=10^9+7$.
|
||||||
This can be done by changing the code so that
|
This can be done by changing the code so that
|
||||||
all calculations are done in modulo $m$.
|
all calculations are done modulo $m$.
|
||||||
In the above code, it is enough to add the line
|
In the above code, it suffices to add the line
|
||||||
\begin{lstlisting}
|
\begin{lstlisting}
|
||||||
d[i] %= m;
|
d[i] %= m;
|
||||||
\end{lstlisting}
|
\end{lstlisting}
|
||||||
|
@ -380,7 +379,7 @@ after the line
|
||||||
d[i] += d[i-c[j]];
|
d[i] += d[i-c[j]];
|
||||||
\end{lstlisting}
|
\end{lstlisting}
|
||||||
|
|
||||||
Now we have covered all basic
|
Now we have discussed all basic
|
||||||
techniques related to
|
techniques related to
|
||||||
dynamic programming.
|
dynamic programming.
|
||||||
Since dynamic programming can be used
|
Since dynamic programming can be used
|
||||||
|
@ -397,7 +396,7 @@ Given an array that contains $n$
|
||||||
numbers $x_1,x_2,\ldots,x_n$,
|
numbers $x_1,x_2,\ldots,x_n$,
|
||||||
our task is to find the
|
our task is to find the
|
||||||
\key{longest increasing subsequence}
|
\key{longest increasing subsequence}
|
||||||
in the array.
|
of the array.
|
||||||
This is a sequence of array elements
|
This is a sequence of array elements
|
||||||
that goes from left to right,
|
that goes from left to right,
|
||||||
and each element in the sequence is larger
|
and each element in the sequence is larger
|
||||||
|
@ -496,8 +495,8 @@ where $i<k$ and $x_i<x_k$. In this case $f(k)=f(i)+1$.
|
||||||
|
|
||||||
For example, in the above example $f(7)=4$,
|
For example, in the above example $f(7)=4$,
|
||||||
because the subsequence $[2,5,7]$ of length 3
|
because the subsequence $[2,5,7]$ of length 3
|
||||||
ends at position 5, and after adding the element
|
ends at position 5, and by adding the element
|
||||||
at position 7 to the subsequence,
|
at position 7 to this subsequence,
|
||||||
we get the optimal subsequence $[2,5,7,8]$ of length 4.
|
we get the optimal subsequence $[2,5,7,8]$ of length 4.
|
||||||
|
|
||||||
An easy way to calculate the
|
An easy way to calculate the
|
||||||
|
@ -514,7 +513,7 @@ Our next problem is to find a path
|
||||||
in an $n \times n$ grid
|
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 such that
|
||||||
we can only move down and right.
|
we only move down and right.
|
||||||
Each square contains a number,
|
Each square contains a number,
|
||||||
and the path should be constructed so
|
and the path should be constructed so
|
||||||
that the sum of numbers along
|
that the sum of numbers along
|
||||||
|
@ -570,17 +569,17 @@ upper-left corner to the lower-right corner.
|
||||||
|
|
||||||
We can approach the problem by
|
We can approach the problem by
|
||||||
calculating for each square $(y,x)$
|
calculating for each square $(y,x)$
|
||||||
the largest possible sum on a path
|
the maximum sum on a path
|
||||||
from the upper-left corner to square $(y,x)$.
|
from the upper-left corner to square $(y,x)$.
|
||||||
Let $f(y,x)$ denote this sum,
|
Let $f(y,x)$ denote this sum,
|
||||||
so $f(n,n)$ is the largest sum on a path
|
so $f(n,n)$ is the maximum sum on a path
|
||||||
from the upper-left corner to
|
from the upper-left corner to
|
||||||
the lower-right corner.
|
the lower-right corner.
|
||||||
|
|
||||||
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)$
|
||||||
can either come from square $(y,x-1)$
|
can come either from square $(y,x-1)$
|
||||||
or from square $(y-1,x)$:
|
or square $(y-1,x)$:
|
||||||
\begin{center}
|
\begin{center}
|
||||||
\begin{tikzpicture}[scale=.65]
|
\begin{tikzpicture}[scale=.65]
|
||||||
\begin{scope}
|
\begin{scope}
|
||||||
|
@ -682,7 +681,7 @@ denote the smallest possible total weight
|
||||||
when a subset of objects
|
when a subset of objects
|
||||||
$1 \ldots k$ is selected such
|
$1 \ldots k$ is selected such
|
||||||
that the total weight is $u$.
|
that the total weight is $u$.
|
||||||
The solution for the problem is the
|
The solution to the problem is the
|
||||||
largest value $u$
|
largest value $u$
|
||||||
for which $0 \le u \le s$ and $f(n,u) \le x$
|
for which $0 \le u \le s$ and $f(n,u) \le x$
|
||||||
where $s=\sum_{i=1}^n a_i$.
|
where $s=\sum_{i=1}^n a_i$.
|
||||||
|
@ -711,8 +710,8 @@ depends on the values of the objects.
|
||||||
|
|
||||||
The \key{edit distance} or \key{Levenshtein distance}
|
The \key{edit distance} or \key{Levenshtein distance}
|
||||||
is the minimum number of editing operations
|
is the minimum number of editing operations
|
||||||
needed for transforming the first string
|
needed to transform a string
|
||||||
into the second string.
|
into another string.
|
||||||
The allowed editing operations are as follows:
|
The allowed editing operations are as follows:
|
||||||
\begin{itemize}
|
\begin{itemize}
|
||||||
\item insert a character (e.g. \texttt{ABC} $\rightarrow$ \texttt{ABCA})
|
\item insert a character (e.g. \texttt{ABC} $\rightarrow$ \texttt{ABCA})
|
||||||
|
@ -721,10 +720,10 @@ The allowed editing operations are as follows:
|
||||||
\end{itemize}
|
\end{itemize}
|
||||||
|
|
||||||
For example, the edit distance between
|
For example, the edit distance between
|
||||||
\texttt{LOVE} and \texttt{MOVIE} is 2
|
\texttt{LOVE} and \texttt{MOVIE} is 2,
|
||||||
because we can first perform operation
|
because we can first perform the operation
|
||||||
\texttt{LOVE} $\rightarrow$ \texttt{MOVE}
|
\texttt{LOVE} $\rightarrow$ \texttt{MOVE}
|
||||||
(change) and then operation
|
(change) and then the operation
|
||||||
\texttt{MOVE} $\rightarrow$ \texttt{MOVIE}
|
\texttt{MOVE} $\rightarrow$ \texttt{MOVIE}
|
||||||
(insertion).
|
(insertion).
|
||||||
This is the smallest possible number of operations,
|
This is the smallest possible number of operations,
|
||||||
|
@ -736,7 +735,7 @@ Suppose we are given strings
|
||||||
$n$ and $m$ characters, respectively,
|
$n$ and $m$ characters, respectively,
|
||||||
and we wish to calculate the edit distance
|
and we wish to calculate the edit distance
|
||||||
between them.
|
between them.
|
||||||
This can be efficiently done using
|
This can be done using
|
||||||
dynamic programming in $O(nm)$ time.
|
dynamic programming in $O(nm)$ time.
|
||||||
Let $f(a,b)$ denote the edit distance
|
Let $f(a,b)$ denote the edit distance
|
||||||
between the first $a$ characters of \texttt{x}
|
between the first $a$ characters of \texttt{x}
|
||||||
|
@ -756,7 +755,7 @@ and in the general case the formula is
|
||||||
where $c=0$ if the $a$th character of \texttt{x}
|
where $c=0$ if the $a$th character of \texttt{x}
|
||||||
equals the $b$th character of \texttt{y},
|
equals the $b$th character of \texttt{y},
|
||||||
and otherwise $c=1$.
|
and otherwise $c=1$.
|
||||||
The formula considers all ways how to shorten the strings:
|
The formula considers all possible ways to shorten the strings:
|
||||||
\begin{itemize}
|
\begin{itemize}
|
||||||
\item $f(a,b-1)$ means that a character is inserted to \texttt{x}
|
\item $f(a,b-1)$ means that a character is inserted to \texttt{x}
|
||||||
\item $f(a-1,b)$ means that a character is removed from \texttt{x}
|
\item $f(a-1,b)$ means that a character is removed from \texttt{x}
|
||||||
|
@ -819,7 +818,7 @@ in the example case:
|
||||||
\end{center}
|
\end{center}
|
||||||
|
|
||||||
The lower-right corner of the table
|
The lower-right corner of the table
|
||||||
indicates that the edit distance between
|
tells us that the edit distance between
|
||||||
\texttt{LOVE} and \texttt{MOVIE} is 2.
|
\texttt{LOVE} and \texttt{MOVIE} is 2.
|
||||||
The table also shows how to construct
|
The table also shows how to construct
|
||||||
the shortest sequence of editing operations.
|
the shortest sequence of editing operations.
|
||||||
|
@ -889,7 +888,7 @@ the edit distance between \texttt{LOV} and \texttt{MOV}, etc.
|
||||||
|
|
||||||
\section{Counting tilings}
|
\section{Counting tilings}
|
||||||
|
|
||||||
Sometimes the states in a dynamic programming solution
|
Sometimes the states of a dynamic programming solution
|
||||||
are more complex than fixed combinations of numbers.
|
are more complex than fixed combinations of numbers.
|
||||||
As an example,
|
As an example,
|
||||||
we consider the problem of calculating
|
we consider the problem of calculating
|
||||||
|
@ -971,9 +970,9 @@ so that the shorter side has length $m$,
|
||||||
because the factor $4^{2m}$ dominates the time complexity.
|
because the factor $4^{2m}$ dominates the time complexity.
|
||||||
|
|
||||||
It is possible to make the solution more efficient
|
It is possible to make the solution more efficient
|
||||||
by using a better representation for the rows as strings.
|
by using a better representation for the rows.
|
||||||
It turns out that it is sufficient to know the
|
It turns out that it is sufficient to know which
|
||||||
columns of the previous row that contain the first square
|
columns of the previous row contain the upper square
|
||||||
of a vertical tile.
|
of a vertical tile.
|
||||||
Thus, we can represent a row using only characters
|
Thus, we can represent a row using only characters
|
||||||
$\sqcap$ and $\Box$, where $\Box$ is a combination
|
$\sqcap$ and $\Box$, where $\Box$ is a combination
|
||||||
|
|
Loading…
Reference in New Issue