Chapter 10 first version
This commit is contained in:
parent
0899147194
commit
3c90715060
149
luku10.tex
149
luku10.tex
|
@ -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++) {
|
||||||
|
|
Loading…
Reference in New Issue