Use 0-indexing with C++ arrays
This commit is contained in:
parent
11564fd4d3
commit
35d53d39d4
7 changed files with 616 additions and 635 deletions
124
chapter05.tex
124
chapter05.tex
|
|
@ -22,9 +22,9 @@ dynamic programming, may be needed.
|
|||
|
||||
We first consider the problem of generating
|
||||
all subsets of a set of $n$ elements.
|
||||
For example, the subsets of $\{1,2,3\}$ are
|
||||
$\emptyset$, $\{1\}$, $\{2\}$, $\{3\}$, $\{1,2\}$,
|
||||
$\{1,3\}$, $\{2,3\}$ and $\{1,2,3\}$.
|
||||
For example, the subsets of $\{0,1,2\}$ are
|
||||
$\emptyset$, $\{0\}$, $\{1\}$, $\{2\}$, $\{0,1\}$,
|
||||
$\{0,2\}$, $\{1,2\}$ and $\{0,1,2\}$.
|
||||
There are two common methods for this:
|
||||
we can either implement a recursive search
|
||||
or use bit operations of integers.
|
||||
|
|
@ -35,21 +35,21 @@ An elegant way to go through all subsets
|
|||
of a set is to use recursion.
|
||||
The following function
|
||||
generates the subsets of the set
|
||||
$\{1,2,\ldots,n\}$.
|
||||
The function maintains a vector \texttt{v}
|
||||
$\{0,1,\ldots,n-1\}$.
|
||||
The function maintains a vector \texttt{subset}
|
||||
that will contain the elements of each subset.
|
||||
The search begins when the function is called
|
||||
with parameter 1.
|
||||
with parameter 0.
|
||||
|
||||
\begin{lstlisting}
|
||||
void gen(int k) {
|
||||
if (k == n+1) {
|
||||
// process subset v
|
||||
if (k == n) {
|
||||
// process subset
|
||||
} else {
|
||||
gen(k+1);
|
||||
v.push_back(k);
|
||||
subset.push_back(k);
|
||||
gen(k+1);
|
||||
v.pop_back();
|
||||
subset.pop_back();
|
||||
}
|
||||
}
|
||||
\end{lstlisting}
|
||||
|
|
@ -59,7 +59,7 @@ candidate to be included in the subset.
|
|||
The function considers two cases that both
|
||||
generate a recursive call:
|
||||
either $k$ is included or not included in the subset.
|
||||
Finally, when $k=n+1$, all elements have been processed
|
||||
Finally, when $k=n$, all elements have been processed
|
||||
and one subset has been generated.
|
||||
|
||||
The following tree illustrates how the function is
|
||||
|
|
@ -72,41 +72,41 @@ We can always choose either the left branch
|
|||
\begin{tikzpicture}[scale=.45]
|
||||
\begin{scope}
|
||||
\small
|
||||
\node at (0,0) {$\texttt{gen}(1)$};
|
||||
\node at (0,0) {$\texttt{gen}(0)$};
|
||||
|
||||
\node at (-8,-4) {$\texttt{gen}(2)$};
|
||||
\node at (8,-4) {$\texttt{gen}(2)$};
|
||||
\node at (-8,-4) {$\texttt{gen}(1)$};
|
||||
\node at (8,-4) {$\texttt{gen}(1)$};
|
||||
|
||||
\path[draw,thick,->] (0,0-0.5) -- (-8,-4+0.5);
|
||||
\path[draw,thick,->] (0,0-0.5) -- (8,-4+0.5);
|
||||
|
||||
\node at (-12,-8) {$\texttt{gen}(3)$};
|
||||
\node at (-4,-8) {$\texttt{gen}(3)$};
|
||||
\node at (4,-8) {$\texttt{gen}(3)$};
|
||||
\node at (12,-8) {$\texttt{gen}(3)$};
|
||||
\node at (-12,-8) {$\texttt{gen}(2)$};
|
||||
\node at (-4,-8) {$\texttt{gen}(2)$};
|
||||
\node at (4,-8) {$\texttt{gen}(2)$};
|
||||
\node at (12,-8) {$\texttt{gen}(2)$};
|
||||
|
||||
\path[draw,thick,->] (-8,-4-0.5) -- (-12,-8+0.5);
|
||||
\path[draw,thick,->] (-8,-4-0.5) -- (-4,-8+0.5);
|
||||
\path[draw,thick,->] (8,-4-0.5) -- (4,-8+0.5);
|
||||
\path[draw,thick,->] (8,-4-0.5) -- (12,-8+0.5);
|
||||
|
||||
\node at (-14,-12) {$\texttt{gen}(4)$};
|
||||
\node at (-10,-12) {$\texttt{gen}(4)$};
|
||||
\node at (-6,-12) {$\texttt{gen}(4)$};
|
||||
\node at (-2,-12) {$\texttt{gen}(4)$};
|
||||
\node at (2,-12) {$\texttt{gen}(4)$};
|
||||
\node at (6,-12) {$\texttt{gen}(4)$};
|
||||
\node at (10,-12) {$\texttt{gen}(4)$};
|
||||
\node at (14,-12) {$\texttt{gen}(4)$};
|
||||
\node at (-14,-12) {$\texttt{gen}(3)$};
|
||||
\node at (-10,-12) {$\texttt{gen}(3)$};
|
||||
\node at (-6,-12) {$\texttt{gen}(3)$};
|
||||
\node at (-2,-12) {$\texttt{gen}(3)$};
|
||||
\node at (2,-12) {$\texttt{gen}(3)$};
|
||||
\node at (6,-12) {$\texttt{gen}(3)$};
|
||||
\node at (10,-12) {$\texttt{gen}(3)$};
|
||||
\node at (14,-12) {$\texttt{gen}(3)$};
|
||||
|
||||
\node at (-14,-13.5) {$\emptyset$};
|
||||
\node at (-10,-13.5) {$\{3\}$};
|
||||
\node at (-6,-13.5) {$\{2\}$};
|
||||
\node at (-2,-13.5) {$\{2,3\}$};
|
||||
\node at (2,-13.5) {$\{1\}$};
|
||||
\node at (6,-13.5) {$\{1,3\}$};
|
||||
\node at (10,-13.5) {$\{1,2\}$};
|
||||
\node at (14,-13.5) {$\{1,2,3\}$};
|
||||
\node at (-10,-13.5) {$\{2\}$};
|
||||
\node at (-6,-13.5) {$\{1\}$};
|
||||
\node at (-2,-13.5) {$\{1,2\}$};
|
||||
\node at (2,-13.5) {$\{0\}$};
|
||||
\node at (6,-13.5) {$\{0,2\}$};
|
||||
\node at (10,-13.5) {$\{0,1\}$};
|
||||
\node at (14,-13.5) {$\{0,1,2\}$};
|
||||
|
||||
|
||||
\path[draw,thick,->] (-12,-8-0.5) -- (-14,-12+0.5);
|
||||
|
|
@ -135,14 +135,14 @@ The usual convention is that the $k$th element
|
|||
is included in the subset exactly when the $k$th last bit
|
||||
in the sequence is one.
|
||||
For example, the bit representation of 25
|
||||
is 11001, that corresponds to the subset $\{1,4,5\}$.
|
||||
is 11001, that corresponds to the subset $\{0,3,4\}$.
|
||||
|
||||
The following code goes through all subsets
|
||||
of a set of $n$ elements
|
||||
|
||||
\begin{lstlisting}
|
||||
for (int b = 0; b < (1<<n); b++) {
|
||||
// process subset b
|
||||
// process subset
|
||||
}
|
||||
\end{lstlisting}
|
||||
|
||||
|
|
@ -154,9 +154,9 @@ elements in the subset.
|
|||
|
||||
\begin{lstlisting}
|
||||
for (int b = 0; b < (1<<n); b++) {
|
||||
vector<int> v;
|
||||
vector<int> subset;
|
||||
for (int i = 0; i < n; i++) {
|
||||
if (b&(1<<i)) v.push_back(i+1);
|
||||
if (b&(1<<i)) subset.push_back(i);
|
||||
}
|
||||
}
|
||||
\end{lstlisting}
|
||||
|
|
@ -167,9 +167,9 @@ for (int b = 0; b < (1<<n); b++) {
|
|||
|
||||
Next we will consider the problem of generating
|
||||
all permutations of a set of $n$ elements.
|
||||
For example, the permutations of $\{1,2,3\}$ are
|
||||
$(1,2,3)$, $(1,3,2)$, $(2,1,3)$, $(2,3,1)$,
|
||||
$(3,1,2)$ and $(3,2,1)$.
|
||||
For example, the permutations of $\{0,1,2\}$ are
|
||||
$(0,1,2)$, $(0,2,1)$, $(1,0,2)$, $(1,2,0)$,
|
||||
$(2,0,1)$ and $(2,1,0)$.
|
||||
Again, there are two approaches:
|
||||
we can either use recursion or go through the
|
||||
permutations iteratively.
|
||||
|
|
@ -179,36 +179,34 @@ permutations iteratively.
|
|||
Like subsets, permutations can be generated
|
||||
using recursion.
|
||||
The following function goes
|
||||
through the permutations of the set $\{1,2,\ldots,n\}$.
|
||||
The function builds a vector \texttt{v} that contains
|
||||
through the permutations of the set $\{0,1,\ldots,n-1\}$.
|
||||
The function builds a vector \texttt{perm} that contains
|
||||
the elements in the permutation,
|
||||
and the search begins when the function is
|
||||
called without parameters.
|
||||
|
||||
\begin{lstlisting}
|
||||
void gen() {
|
||||
if (v.size() == n) {
|
||||
// process permutation v
|
||||
if (perm.size() == n) {
|
||||
// process permutation
|
||||
} else {
|
||||
for (int i = 1; i <= n; i++) {
|
||||
if (p[i]) continue;
|
||||
p[i] = 1;
|
||||
v.push_back(i);
|
||||
for (int i = 0; i < n; i++) {
|
||||
if (chosen[i]) continue;
|
||||
chosen[i] = true;
|
||||
perm.push_back(i);
|
||||
gen();
|
||||
p[i] = 0;
|
||||
v.pop_back();
|
||||
chosen[i] = false;
|
||||
perm.pop_back();
|
||||
}
|
||||
}
|
||||
}
|
||||
\end{lstlisting}
|
||||
|
||||
Each function call adds a new element to
|
||||
the vector \texttt{v}.
|
||||
The array \texttt{p} indicates which
|
||||
elements are already included in the permutation:
|
||||
if $\texttt{p}[k]=0$, element $k$ is not included,
|
||||
and if $\texttt{p}[k]=1$, element $k$ is included.
|
||||
If the size of \texttt{v} equals the size of the set,
|
||||
the vector \texttt{perm}.
|
||||
The array \texttt{chosen} indicates which
|
||||
elements are already included in the permutation.
|
||||
If the size of \texttt{perm} equals the size of the set,
|
||||
a permutation has been generated.
|
||||
|
||||
\subsubsection{Method 2}
|
||||
|
|
@ -224,13 +222,13 @@ The C++ standard library contains the function
|
|||
\texttt{next\_permutation} that can be used for this:
|
||||
|
||||
\begin{lstlisting}
|
||||
vector<int> v;
|
||||
for (int i = 1; i <= n; i++) {
|
||||
v.push_back(i);
|
||||
vector<int> perm;
|
||||
for (int i = 0; i < n; i++) {
|
||||
perm.push_back(i);
|
||||
}
|
||||
do {
|
||||
// process permutation v
|
||||
} while (next_permutation(v.begin(),v.end()));
|
||||
// process permutation
|
||||
} while (next_permutation(perm.begin(),perm.end()));
|
||||
\end{lstlisting}
|
||||
|
||||
\section{Backtracking}
|
||||
|
|
@ -344,7 +342,7 @@ The following code implements the search:
|
|||
\begin{lstlisting}
|
||||
void search(int y) {
|
||||
if (y == n) {
|
||||
c++;
|
||||
count++;
|
||||
return;
|
||||
}
|
||||
for (int x = 0; x < n; x++) {
|
||||
|
|
@ -359,7 +357,7 @@ void search(int y) {
|
|||
The search begins by calling \texttt{search(0)}.
|
||||
The size of the board is $n$,
|
||||
and the code calculates the number of solutions
|
||||
to $c$.
|
||||
to \texttt{count}.
|
||||
|
||||
The code assumes that the rows and columns
|
||||
of the board are numbered from 0.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue