Chapter 10 first version

This commit is contained in:
Antti H S Laaksonen 2017-01-07 15:35:53 +02:00
parent 0899147194
commit 3c90715060
1 changed files with 77 additions and 74 deletions

View File

@ -377,66 +377,66 @@ do {
% $\emptyset$, $\{2\}$, $\{5\}$, $\{7\}$, % $\emptyset$, $\{2\}$, $\{5\}$, $\{7\}$,
% $\{2,5\}$, $\{2,7\}$, $\{5,7\}$ ja $\{2,5,7\}$. % $\{2,5\}$, $\{2,7\}$, $\{5,7\}$ ja $\{2,5,7\}$.
\section{Dynaaminen ohjelmointi} \section{Dynamic programming}
\subsubsection{Permutaatioista osajoukoiksi} \subsubsection{From permutations to subsets}
Dynaamisen ohjelmoinnin avulla on usein mahdollista Using dynamic programming, it is often possible
muuttaa permutaatioiden läpikäynti osajoukkojen läpikäynniksi. to change iteration over permutations into
Tällöin dynaamisen ohjelmoinnin tilana on iteration over subsets.
joukon osajoukko sekä mahdollisesti muuta tietoa. In this case, the dynamic programming state
contains a subset of a set and possibly
some additional information.
Tekniikan hyötynä on, The benefit in this technique is that
että $n$-alkioisen joukon permutaatioiden määrä $n!$ $n!$, the number of permutations of an $n$ element set,
on selvästi suurempi kuin osajoukkojen määrä $2^n$. is much larger than $2^n$, the number of subsets.
Esimerkiksi jos $n=20$, niin $n!=2432902008176640000$, For example, if $n=20$, then
kun taas $2^n=1048576$. $n!=2432902008176640000$ and $2^n=1048576$.
Niinpä tietyillä $n$:n arvoilla permutaatioita ei ehdi Thus, for certain values of $n$,
käydä läpi mutta osajoukot ehtii käydä läpi. we can go through subsets but not through permutations.
Lasketaan esimerkkinä, monessako As an example, let's calculate the number of
joukon $\{0,1,\ldots,n-1\}$ permutations of set $\{0,1,\ldots,n-1\}$
permutaatiossa ei ole where the difference between any two successive
missään kohdassa kahta peräkkäistä lukua. elements is larger than one.
Esimerkiksi tapauksessa $n=4$ ratkaisuja on kaksi: For example, there are two solutions for $n=4$:
\begin{itemize} \begin{itemize}
\item $(1,3,0,2)$ \item $(1,3,0,2)$
\item $(2,0,3,1)$ \item $(2,0,3,1)$
\end{itemize} \end{itemize}
Merkitään $f(x,k)$:llä, Let $f(x,k)$ denote the number of permutations
monellako tavalla osajoukon for a subset $x$
$x$ luvut voi järjestää niin, where the last number is $k$ and
että viimeinen luku on $k$ ja missään kohdassa the difference between any two successive
ei ole kahta peräkkäistä lukua. elements is larger than one.
Esimerkiksi $f(\{0,1,3\},1)=1$, For example, $f(\{0,1,3\},1)=1$
koska voidaan muodostaa permutaatio $(0,3,1)$, because there is a permutation $(0,3,1)$,
ja $f(\{0,1,3\},3)=0$, koska 0 ja 1 eivät and $f(\{0,1,3\},3)=0$ because 0 and 1
voi olla peräkkäin alussa. can't be next to each other.
Funktion $f$ avulla ratkaisu tehtävään Using $f$, the solution for the problem is the sum
on summa
\[ \sum_{i=0}^{n-1} f(\{0,1,\ldots,n-1\},i). \] \[ \sum_{i=0}^{n-1} f(\{0,1,\ldots,n-1\},i). \]
\noindent \noindent
Dynaamisen ohjelmoinnin tilat voi The dynamic programming states can be stored as follows:
tallentaa seuraavasti:
\begin{lstlisting} \begin{lstlisting}
long long d[1<<n][n]; long long d[1<<n][n];
\end{lstlisting} \end{lstlisting}
\noindent \noindent
Perustapauksena $f(\{k\},k)=1$ kaikilla $k$:n arvoilla: First, $f(\{k\},k)=1$ for all values of $k$:
\begin{lstlisting} \begin{lstlisting}
for (int i = 0; i < n; i++) d[1<<i][i] = 1; for (int i = 0; i < n; i++) d[1<<i][i] = 1;
\end{lstlisting} \end{lstlisting}
\noindent \noindent
Tämän jälkeen muut funktion arvot After this, the other values can be calculated
saa laskettua seuraavasti: as follows:
\begin{lstlisting} \begin{lstlisting}
for (int b = 0; b < (1<<n); b++) { for (int b = 0; b < (1<<n); b++) {
@ -451,15 +451,15 @@ for (int b = 0; b < (1<<n); b++) {
\end{lstlisting} \end{lstlisting}
\noindent \noindent
Muuttujassa $b$ on osajoukon bittiesitys, The variable $b$ contains the bit representation
ja osajoukon luvuista muodostettu of the subset, and the corresponding
permutaatio on muotoa $(\ldots,j,i)$. permutation is of the form $(\ldots,j,i)$.
Vaatimukset ovat, että lukujen $i$ ja $j$ It is required that the difference between
etäisyyden tulee olla yli 1 $i$ and $j$ is larger than 1, and the
ja lukujen tulee olla osajoukossa $b$. numbers belong to subset $b$.
Lopuksi ratkaisujen määrän saa laskettua näin Finally, the number of solutions can be
muuttujaan $s$: calculated as follows to $s$:
\begin{lstlisting} \begin{lstlisting}
long long s = 0; long long s = 0;
@ -468,18 +468,19 @@ for (int i = 0; i < n; i++) {
} }
\end{lstlisting} \end{lstlisting}
\subsubsection{Osajoukkojen summat} \subsubsection{Sums of subsets}
Oletetaan sitten, että jokaista Let's assume that every subset $x$
joukon $\{0,1,\ldots,n-1\}$ of $\{0,1,\ldots,n-1\}$
osajoukkoa $x$ vastaa arvo $c(x)$ ja is assigned a value $c(x)$,
tehtävänä on laskea kullekin and our task is to calculate for
osajoukolle $x$ summa each subset $x$ the sum
\[s(x)=\sum_{y \subset x} c(y)\] \[s(x)=\sum_{y \subset x} c(y)\]
eli bittimuodossa ilmaistuna that corresponds to the sum
\[s(x)=\sum_{y \& x = y} c(y). \] \[s(x)=\sum_{y \& x = y} c(y)\]
Seuraavassa on esimerkki funktioiden arvoista, using bit operations.
kun $n=3$: The following table gives an example of
the values of the functions when $n=3$:
\begin{center} \begin{center}
\begin{tabular}{rrr} \begin{tabular}{rrr}
$x$ & $c(x)$ & $s(x)$ \\ $x$ & $c(x)$ & $s(x)$ \\
@ -494,35 +495,37 @@ $x$ & $c(x)$ & $s(x)$ \\
111 & 0 & 12 \\ 111 & 0 & 12 \\
\end{tabular} \end{tabular}
\end{center} \end{center}
Esimerkiksi $s(110)=c(000)+c(010)+c(100)+c(110)=5$. For example, $s(110)=c(000)+c(010)+c(100)+c(110)=5$.
Tehtävä on mahdollista ratkaista ajassa $O(2^n n)$ The problem can be solved in $O(2^n n)$ time
laskemalla arvoja funktiolle $f(x,k)$: by defining a function $f(x,k)$ that calculates
mikä on lukujen $c(y)$ summa, missä $x$:stä saa $y$:n the sum of values $c(y)$ where $x$ can be
muuttamalla millä tahansa tavalla bittien $0,1,\ldots,k$ converted into $y$ by changing any one bits
joukossa ykkösbittejä nollabiteiksi. in positions $0,1,\ldots,k$ to zero bits.
Tämän funktion avulla ilmaistuna $s(x)=f(x,n-1)$. Using this function, the solution for the
problem is $s(x)=f(x,n-1)$.
Funktion pohjatapaukset ovat: The base cases for the function are:
\begin{equation*} \begin{equation*}
f(x,0) = \begin{cases} f(x,0) = \begin{cases}
c(x) & \textrm{jos $x$:n bitti 0 on 0}\\ c(x) & \textrm{if bit 0 in $x$ is 0}\\
c(x)+c(x \XOR 1) & \textrm{jos $x$:n bitti 0 on 1}\\ c(x)+c(x \XOR 1) & \textrm{if bit 0 in $x$ is 1}\\
\end{cases} \end{cases}
\end{equation*} \end{equation*}
Suuremmille $k$:n arvoille pätee seuraava rekursio: For larger values of $k$, the following recursion holds:
\begin{equation*} \begin{equation*}
f(x,k) = \begin{cases} f(x,k) = \begin{cases}
f(x,k-1) & \textrm{jos $x$:n bitti $k$ on 0}\\ f(x,k-1) & \textrm{if bit $k$ in $x$ is 0}\\
f(x,k-1)+f(x \XOR (1 < < k),k-1) & \textrm{jos $x$:n bitti $k$ on 1}\\ f(x,k-1)+f(x \XOR (1 < < k),k-1) & \textrm{if bit $k$ in $x$ is 1}\\
\end{cases} \end{cases}
\end{equation*} \end{equation*}
Niinpä funktion arvot voi laskea seuraavasti Thus, we can calculate the values for the function
dynaamisella ohjelmoinnilla. as follows using dynamic programming.
Koodi olettaa, että taulukko \texttt{c} sisältää The code assumes that the array \texttt{c}
funktion $c$ arvot ja muodostaa taulukon \texttt{s}, contains the values for $c$,
jossa on funktion $s$ arvot. and it constructs an array \texttt{s}
that contains the values for $s$.
\begin{lstlisting} \begin{lstlisting}
for (int x = 0; x < (1<<n); x++) { for (int x = 0; x < (1<<n); x++) {
f[x][0] = c[x]; f[x][0] = c[x];
@ -537,9 +540,9 @@ for (int k = 1; k < n; k++) {
} }
\end{lstlisting} \end{lstlisting}
Itse asiassa saman laskennan voi toteuttaa lyhyemmin Actually, a much shorter implementation is possible
seuraavasti niin, että tulokset lasketaan because we can calculate the results directly
suoraan taulukkoon \texttt{s}: to array \texttt{s}:
\begin{lstlisting} \begin{lstlisting}
for (int x = 0; x < (1<<n); x++) s[x] = c[x]; for (int x = 0; x < (1<<n); x++) s[x] = c[x];
for (int k = 0; k < n; k++) { for (int k = 0; k < n; k++) {