CATEGORII DOCUMENTE |
Bulgara | Ceha slovaca | Croata | Engleza | Estona | Finlandeza | Franceza |
Germana | Italiana | Letona | Lituaniana | Maghiara | Olandeza | Poloneza |
Sarba | Slovena | Spaniola | Suedeza | Turca | Ucraineana |
DOCUMENTE SIMILARE |
|
iame paragrafe aptarsime pagrindinius kombinatorinių objektų (derinių, kėlinių, aibės iskaidymo ir kt.) generavimo algoritmus.
Optimali tokių objektų generavimo algoritmo struktūra yra:
begin
generuoti pradinį junginį (kombinatorinį objekt¹);
while generavimo s¹lyga do
begin
nagrinėti (spausdinti) junginį (kombinatorinį objekt¹);
generuoti junginį (kombinatorinį objekt¹), gretim¹ inagrinėtam (atspausdintam).
end
end
Priklausomai nuo pasirinktų objektų bei jų generavimo tvarkos, iame algoritme turi būti konkretizuoti sakiniai generuoti pradinį junginį, generavimo s¹lyga, generuoti gretim¹ junginį.
Pirmiausia aptersime
derinių generavimo leksikografine didėjimo tvarka
algoritm¹. Apie leksikografinź vektorių tvark¹ kalbėjome 1.3
paragrafe. Čia priminsime, kad jei į derinį iūrėsime kaip
į skaičių, tai deriniams atitinkantys skaičiai bus idėstyti
didėjimo tvarka.
Pavyzdys. Panagrinėkime . Deriniai,
surayti leksikografine tvarka, bus:
Derinius nuosekliai talpinsime masyve
ir io masyvo
elementai apibrė derinį.
Pradinio derinio generavimas. Aiku, kad pradinis derinys generuojamas taip:
for l 0 to k do c [l] := l;
Kaip generuoti patį maiausi¹ leksikografikai didesnį derinį nei turimas?
Tarkime, turimas derinys. Leksikografine tvarka pats
didiausias derinys yra:
. Vadinasi,
,
.
todėl, norint apskaičiuoti patį maiausi¹ leksikografikai
didesnį derinį nei nagrinėjamas derinys, elgsimės taip:
masyve rasime pirm¹ i deinės element¹ cl,
,
tenkinantį s¹lyg¹
;
į
element¹ padidinsime vienetu, t.y. ;
likusius elementus upildysime i eilės einančiais natūraliaisiais skaičiais, t.y.
for i l + 1 to k do ci: = ci-1 + 1;
Generavimo pabaigos s¹lyga. Jei pirmasis i deinės elementas, tenkinantis
s¹lyg¹ , yra
, tai
reikia, kad nagrinėjame derinį:
. Vadinasi,
jau visi deriniai sugeneruoti.
Tuo būdu,
derinių generavimo leksikografine tvarka algoritmas
yra.
Duota: n objektų skaičius,
k objektų skaičius derinyje.
Rasti: generuoti derinius leksikografine tvarka.
begin
for l := 0 to k do c [l] := l;
p := true;
while p do
begin
spausdinti
derinį
l := k;
while (l >= 1) and c [l] >= n k + l do l := l 1;
if l = 0 then p := false
else begin
c [l] := c [l] + 1;
for i := l + 1 to k do c [i] := c [i 1] + 1;
end
end
end
Kaip matyti i antrojo
Grėjaus kodo generavimo algoritmo (r. 1.3 paragraf¹), Grėjaus kodus
galima generuoti i pradinio kodo, inant sek¹ . ios sekos
elementas
ymi skiltį, kuri¹ reikia invertuoti, kad
i
-ojo kodo
gautume i-¹jį kod¹.
Pavyzdiui, kai , seka T3 yra tokia:
.
Vadinasi, pakanka mokėti efektyviai generuoti sek¹ Tn, kad galėtume generuoti Grėjaus kodus.
Sek¹ Tn galima efektyviai generuoti naudojant stek¹.
Pradioje stekas
upildomas elementais: (viruje yra elementas 1). Algoritmas ima
virutinį steko element¹ i ir
patalpina jį į sek¹ Tn;
po to į stek¹ įraomi elementai
.
Būtent tokiu būdu emiau pateiktas algoritmas generuoja Grėjaus
kodus.
begin
s
for j := n downto 1 do begin
g [j] := 0;
s j
end
while s ¹ Æ do
begin
spausdinti
i s
g [i] := 1 g [i];
for j := i 1 downto 1 do s j
end
end
end
Skaičiuojant pagal
į algoritm¹, steko turinys (virutinis elementas yra steko
virūnėje) kis taip: , o i reikmės sudarys T3 sek¹
.
Pateikt¹ algoritm¹
galima patobulinti. Kiekvien¹ kart¹, kai į stek¹ patalpinamas elementas , mes
apriori inome, kad vir jo bus patalpinti elementai
. Protingas
ios informacijos panaudojimas įgalina vietoj steko naudoti masyv¹
tokiu būdu. Elementas
yra virutinis steko elementas ir kiekvienam
yra elementas, steke esantis tuoj po elemento j (emiau elemento j), jei j yra steke. Jei
elemento j steke nėra, tai
elemento
reikmė negali turėti jokios
įtakos skaičiavimams ir todėl
priskiriame reikmź
, kadangi
mes inome, kad kai kit¹ kart¹ elementas
bus patalpintas į stek¹, elementu,
esančiu vir jo, bus elementas j. Dar
daugiau, kadangi elementai
bus talpinami į stek¹ paalinus element¹ i, mums reikia tiktai priskirti
, laikant,
kad visiems j,
,
reikmė
buvo priskirta, kai j buvo paalintas i steko (primename, tada
). Pagaliau,
kai
, elementai
į stek¹ patalpinami operacijos
dėka.
Dabar gausime tokį algoritm¹.
begin
for j := 0 to n + 1 do begin
g [j] := 0;
t [j] := j + 1;
end
i
while i < n + 1 do
begin
spausdinti
i t
g [i] := 1 g [i];
t [i 1] := t [i];
t [i] := i + 1;
if i ¹ 1 then t
end
end
Kai , masyvo t turinys skaičiavimo eigoje
kis taip:
Pateikt¹jį
algoritm¹ galima truputį patobulinti. Pastebėsim, jei operatorių
patalpintume po operatoriaus g [i] :=
1 g [i], tai
operatorių if i ¹ 1 then t[0]:=1 galima imesti. I tikro, jei
, tai
operatorius
t [i
1] := t [i] tuoj pat itaisys neteising¹ t [0]
reikmź. Tuo būdu galutinis Grėjaus kodų generavimo algoritmas
bus toks.
begin
for j := 0 to n + 1 do begin
g [j] := 0;
t [j] := j + 1;
end
i
while i < n + 1 do
begin
spausdinti
i t
g [i] := 1 g [i];
t t [i 1] := t [i]; t [i] := i + 1;
end
end
Aptarkome derinių generavimo minimlaus pokyčio tvarka algoritm¹. Minimlaus pokyčio tvarka tai tokia derinių seka, kai bet koks ios sekos derinys yra gaunamas i prie jį stovinčio derinio, pakeitus jame vien¹ element¹ kitu.
Pavyzdys. Panagrinėkime . Deriniai,
surayti minimalaus pokyčio tvarka, bus tokie:
Nesunku pastebėti, kad bet koks ios sekos derinys, iskyrus pirm¹jį, yra gaunamas i prie jį stovinčio derinio, pakeitus vien¹ element¹ kitu.
Jei pirmajame derinyje element¹ 2 pakeisime elementu 4, tai gausime antr¹jį derinį. Jei jame element¹ 1 pakeisime elementu 2, tai gausime treči¹jį derinį ir t.t.
Reikia pastebėti, kad i derinių seka yra uciklinta, t.y. jei paskutiniame derinyje element¹ 5 pakeisime elementu 3, tai gausime pirm¹jį ios sekos derinį.
Kiekvien¹
derinį galima ukoduoti n-skilčiu
dvejetainiu skaičiumi : jei
, tai elementas i priklauso deriniui; jei
, tai elementas i nepriklauso deriniui. Tuo būdu
deriniai
bus ukoduoti n-skilčiais dvejetainiais skaičiais, kiekvienas i kurių turi k vienetukų ir
nulių.
Aiku, kad minimalaus pokyčio derinių sekos kodai bus dvejetainiai skaičiai, turintys k vienetukų, ir bet kokie du gretimi skaičiai skirsis dviem skiltimis: vienoje nulis keičiamas vienetu, o kitoje vienetas keičiamas nuliu.
Pavyzdys. Aukčiau pateikto
minimalaus pokyčio derinių sekos kodai bus:
Tokių kodų generavimas yra glaudiai susijźs su 1.3 paragrafe inagrinėtu Grėjaus kodų generavimu.
Tarkime,
Grėjaus kodai, o
,
seka Grėjaus kodų, turinčių
lygiai k vienetukų. Tada, kaip
parodyta literatūroje [RND80],
seka sutampa su minimalaus pokyčio
derinių seka.
Pavyzdys. Panagrinėkime
Grėjaus kodus, kai . Remiantis
1.3 paragrafe inagrinėtu algoritmu, gausime toki¹
sek¹:
Kodai, turintys 3
vienetukus, pabraukti. Iraź iuos kodus, gausime minimalaus pokyčio derinio
sekos kodus.
Norėdami
efektyviai generuoti ,
, kodus,
pasinaudokime
rekursyviniu apibrėimu:
(3.4.1)
ir
čia ymi kodus, suraytus atvirkčia tvarka, o
reikia, kad n skilčių upildome nuliais, o
kad n
skilčių upildome vienetais.
Pastaroji
rekurentinė formulė generuoja pradedant
ir baigiant
.
Pavyzdys. Remdamiesi (3.4.1) formule, pavaizduokime generavimo medį (r. 3.4.1 pav.).
1 pav. G(5, 3) generavimas, remiantis (3.4.1) rekurentine formule
Remdamiesi iuo mediu, gausime sek¹:
Eilės nr. |
Kodas |
Eilės nr. |
Kodas |
Nesunku parodyti (r.
[RND80]), kad 3.4.1 pav. pavaizduoto binarinio medio kabančios
virūnės yra arba arba
.
Kodų generavimo udavinys transformuojasi į
binarinio medio kabančių virūnių periūr¹: pradedant
virutine ir baigiant apatine.
Norint pereiti nuo vienos kabančios virūnės į gretim¹ kabanči¹ virūnź, nagrinėjame keli¹ i pirmos kabančios virūnės medio aknies link. Tuo keliu link aknies keliaujame virūnėmis, kurios yra apatiniai sūnūs (r. 3.4.1 pav.). Pasiekź pirm¹j¹ virūnź, kuri yra virutinis sūnus, pereiname pas jo brolį (apatinį sūnų) ir i jo, eidami virutiniais sūnumis, einame į kabanči¹ virūnź.
Pavyzdiui (r. 3.4.1
pav.), inagrinėjź kabanči¹ virūnź , pirmiausia
pasieksime virutinį sūnų
ir pereisime pas jo brolį (apatinį
sūnų)
. Ir i jo
virutiniais sūnumis
,
pasieksime virūnei
gretim¹ kabanči¹ virūnź
. (3.4.1
pav. is kelias parykintas).
Nagrinėdami
kabanči¹ binarinio medio virūnź , mes tuo
pačiu inome keli¹ i aknies į kabanči¹ virūnź. Norėdami pereiti
prie gretimos kabančios virūnės, turime saugoti informacij¹ apie
virūnź
, į
kuri¹ turime sugrįti (virūnės
visada yra apatiniai sūnūs). ios
virūnės bus saugomos steke. Toliau pateiktame
generavimo algoritme stekas bus organizuojamas
taip pat, kaip jis buvo organizuotas generuojant Grėjaus kodus (r.
treči¹jį Grėjaus kodų generavimo algoritm¹). Parametras t rodo skaičių vienetukų tarp
skilčių
ir gali būti nesunkiai apskaičiuojamas.
Todėl steke saugoma tik i
reikmė.
Atidiai
ityrinėjus binarinį medį, galima pastebėti, kad
nagrinėjamo kodo, kai i jo grįtama į virūnź ,
perskaičiavimas į gretim¹ kod¹ reiklauja nagrinėti emiau pateiktus
keturis atvejus, priklausomai nuo gi
ir t reikmės:
gi , t > 1
|
gi , t > 0
|
gi , t
|
gi , t
|
ie pertvarkymai turi
įtakos vienetukų skaičiui tarp skilčių : t reikmź turime sumainti 1, jei
, ir
padidinti 1, jei
.
Pereinant prie gretimo kodo yra invertuojamos dvi skiltys:
skiltis ,
ir
Atlikus iuos veiksmus, į stek¹ reikia įrayti papildom¹ informacij¹: tarpines virūnes, esančias tarp nagrinėjamos virūnės ir nagrinėjamos kabančios virūnės. Kadangi tas priklauso nuo virūnės steko viruje, tai t reikmė gali vėl pasikeisti.
Jei arba
, tai
reikia, kad virūnė, kurioje mes esame, yra kabanti
virūnė:
arba
ir jokių tarpinių virūnių
saugoti nereikia. iuo atveju t
visada lygus
.
Kita vertus, jei ir
, tai į
stek¹ turime įtraukti virūnes
, iskyrus
t¹ atvejį, kai
. iuo
atveju į stek¹ įtraukiame tik
.
Parametro t reikmė turi būti
perskaičiuojama. Kadangi tarp vienetukų gali būti tik
, tai
. Be to, jei
iuo atveju t tampa lygus 0, tai
.
emiau pateiktas
derinių generavimo minimalaus pokyčio tvarka
algoritmas. iame algoritme stekas organizuojamas masyvu
, o jo
virutinis elementas yra
(r. treči¹jį Grėjaus kodų
generavimo algoritm¹). Kadangi
, tai
ekvivalentu, kad į stek¹ įtraukiame
.
const nn =
type mas = array [0..nn] of integer;
var n, i, k : integer;
g, tau : mas;
procedure der (n, k : integer);
var i, j, t : integer;
g, tau : mas;
begin
for j := 1 to k do
begin
g [j] := 1;
tau [j] := j + 1;
end
for j := k + 1 to n + 1 do
begin
g [j] := 0;
tau [j] := j + 1;
end
t := k;
tau [1] := k + 1;
i
while i <> n + 1 do
begin
writeln
for j := n downto 1 do write (g [j] : 3);
writeln
i := tau [1];
tau [1] := tau [i];
tau [i] := i + 1;
if g [i] = 1 then
begin
if t <> 0 then g[t]:=1-g[t]
else g[i-1]:=1-g[i-1];
t:=t+1;
end
else
begin
if t <> 1 then g [t 1] := 1 g [t 1]
else g [i 1] := 1 g [i 1];
t := t 1;
end
g [i] :=1 g [i];
if (t = i 1) or (t = 0) then t := t + 1
else
begin
t := t g [i 1];
tau [i 1] := tau [1];
if t = 0 then tau [1] := i 1
else tau [1]:=t+1;
end
end
end
begin
writeln ('įveskite n');
readln (n);
writeln ('įveskite k');
readln (k);
der (n, k);
end
Aptarsime atsitiktinio
poaibio, turinčio k elementų, i
aibės, turinčios n elementų
,
generavim¹. Aiku, kad tokio poaibio generavimo tikimybė yra
.
Tam tikslui
atsitiktinai parenkame vien¹ i n elementų
(pasirinkimo
tikimybė
) ir po to
atsitiktinai generuojame
-elementį
poaibį i likusių
elementų.
Tada ios
procedūros eigoje k-elemenčio
poaibio isirinkimo tikimybė yra tokių
tikimybių sandauga:
P (pirmasis isirinktas elementas
vienas i k elementų
P (antrasis isirinktas elementas
vienas i k 1 likusių elementų)
_ _ __ _ _ __ _ _ __ _ _ __ _ _ __ _ _ _
P (k-asis isirinktas elementas paskutinysis
i likusių elementų) .
i sandauga bus lygi:
Aptarsime atsitiktinio derinio generavimo algoritm¹.
Algoritmo
realizavimui panaudosime papildom¹ masyv¹ p,
kuriame saugosime dar neirinktų elementų numerius. elementai isirinkti, tai
bus s¹raas
elementų, kurie dar neisirinkti. Kadangi
nebūtina isaugoti elementų tvark¹, tai, isirinkus element¹
,
, įjo viet¹ įraome neisirinkt¹
element¹
.
emiau pateikiamas atsitiktinio derinio generavimo algoritmas.
begin
for j := 1 to n do p [j] := j;
R Æ
for j := 1 to k do
begin
r := rand (j, n);
R := R È
p [r] := p [j];
end
end
Aptarsime
kėlinių i n elementų generavimo
leksikografine tvarka udavinį. Sprźsdami į udavinį, laikysime
aukčiau pateiktos (r. 3.4 paragrafo pradi¹) kombinatorinų objektų
generavimo algoritmo struktūros. Norėdami isiaikinti io algoritmo
pagrindinius momentus, panagrinėkime pavyzdį, kai .
Pradinio kodo generavimas. Kėlinį talpinsime masyve , kurio
elementai
ir nusako kėlinį. Aiku, kad
pradinis kėlinys yra
. Pavyzdiu,
jei
, tai
.
Paties maiausio, leksikografikai didesnio
kėlinio nei nagrinėjamas, apskaičiavimas. Tarkime, nagrinėjamas kėlinys. Pavyzdiui,
. Jei į
kėlinį iūrėsime kaip į skaičių, tai reikia rasti
patį maiausi¹ skaičių, didesnį nei nagrinėjamas. Tam
tikslui reikia:
rasti
pirm¹ i deinės por¹ toki¹, kad
,
rasti , t.y tarp
elementų
rasti patį maiausi¹ element¹,
didesnį u
,
elementus
ir
sukeisti vietomis,
elementus
(uodeg¹) surayti atvirkčia tvarka
(apversti).
Pavyzdiui, pirmoji i
deinės pora, tenkinanti 1) punkto reikalavim¹, yra , o
elementas
. Tada,
sukeitź 4 su 5, gausime
. Apvertź
uodeg¹, gausime patį maiausi¹ leksikografikai didesnį
kėlinį nei duotas:
.
Generavimo pabaigos s¹lyga. Aiku, kad pats didiausias kėlinys yra (masyvo
elementas
yra pagalbinis, ir jo reikmė lygi
nuliui). Tada pirma i deinės pora
, tenkinanti
s¹lyg¹
yra
. Kitaip
tariant, jei
, tai
generavimo pabaiga.
Vadinasi,
kėlinių generavimo leksikografine tvarka algoritmas
gali būti uraytas taip.
begin
fo i:= 0 to n do p [i] :=i;
t := true;
while t do
begin
spausdinti
i := n 1;
while p [i] > p [i+ 1] do i := i 1;
if i = 0 then t := false
else
begin
j := n;
while p [j] < p [i] do j := j 1;
pp := p [i]; p [i] := p [j]; p [j] := pp;
k := i + 1; l := n;
while k < l do
begin
pp := p [k]; p [k] := p [l]; p [l] := pp;
k := k + 1; l := l 1;
end
end
end
end
Be kėlinių generavimo leksikografine tvarka naudojamas ir kėlinių generavimo antileksikografine tvarka metodas.
Apibrėimas. Vektorius yra antileksikografikai maesnis u
vektorių
(ymime
), jei
egzistuoja toks
, kad
, o
,
.
Pastebėsime, jei vietoje skaičių
paimtume raides
,
idėstytas natūralia, pavyzdiui, abėcėlės tvarka:
, tai
leksikografinė tvarka apibrė n
ilgio odių isidėstym¹ odyne įprasta tvarka. Tuo tarpu
antileksikografinė tvarka apibrėia odių tvark¹, kai tiek
pozicijų eilikumas sekoje, tie ir aibės elementų
isidėstymas odyje yra atvirkčias.
Pavyzdiui,
uraykime aibės kėlinius leksikografine ir
antileksikografine tvarka.
Leksikografine tvarka:
1, 3, 2; 2, 1, 3; 2, 3, 1; 3, 1, 2; 3, 2, 1.
Antileksikografine tvarka:
2, 1, 3; 1, 3, 2; 3, 1, 2; 2, 3, 1; 3, 2, 1.
I leksikografinės tvarkos kėlinio 1, 3, 2 gausime antileksikografinės tvarkos kėlinį, jei 1-t¹ keisime 3-tu, 3-t¹ keisime 1-tu (imame aibės X elementus atvirkčia tvarka) ir kėlinio pozicijas suraome atvirkčia tvarka. Gausime 3, 1, 2, o po to 2, 1, 3.
Kėlinių
generavimas antileksikografine didėjimo tvarka yra labai panaus į
kėlinių generavimo leksikografine didėjimo tvarka algoritm¹.
Kėlinių generavimui įveskime masyv¹
, kurio
elementai
apibrėia nagrinėjam¹jį
kėlinį.
Pradinio kėlinio generavimas. for i := 1 to n + 1 do p [i] := i;
Paties maiausio antileksikografikai didesnio kėlinio apskaičiavimas. Tam tikslui reikia:
rasti pirm¹ i
kairės por¹ , toki¹, kad
rasti , t.y tarp
elementų
rasti patį didiausi¹ element¹,
maesnį nei
,
elementus ir
sukeisti vietomis,
elementus surayti atvirkčia tvarka.
Generavimo pabaigos s¹lyga. Paskutinysis antileksikografinės tvarkos
kėlinys yra , o
, t.y. masyvo
elementai yra
. Aiku, kad iuo atveju pirmoji i
deinės pora
, tenkinanti 1)-ojo punkto reikalavim¹:
, yra
. Vadinasi, jei
, tai generavimo pabaigos s¹lyga.
Pateiksime
kėlinių generavimo antileksikografine tvarka
algoritm¹.
begin
fo i:= 0 to n + 1 do p [i] :=i;
t := true;
while t do
begin
spausdinti
i
while p [i-1] > p [i] do i := i + 1;
if i = n + 1 then t := false
else
begin
j
while p [j] > p [i] do j := j + 1;
pp := p [i]; p [i] := p [j]; p [j] := pp;
k := 1; l := i - 1;
while k < l do
begin
pp := p [k]; p [k] := p [l]; p [l] := pp;
k := k + 1; l := l 1;
end
end
end
end
Kai , tai
pateiktas algoritmas apskaičiuos
kėlinius:
Panagrinėkime
kėlinių generavimo minimalaus pokyčio tvarka metod¹ ir algoritm¹.
Kėlinių minimalaus pokyčio tvarka tai tokia kėlinių
generavimo seka, kai bet kokie du gretimi kėliniai skiriasi tik
dviejų elementų padėtimi. Pavyzdiui, kai , gautume
sek¹: 1, 2, 3; 1, 3, 2; 3, 1, 2; 3, 2, 1; 2, 3, 1; 2, 1, 3.
Aptarsime kėlinių generavimo tokia tvarka metod¹.
Kai , tai
egzistuoja vienintelis kėlinys: 1. Tarkime, kad turime
kėlinius, tenkinančius minimalaus pokyčio
tvark¹. Tada kėlinį
generuosime taip.
Sunumeruokime visus kėlinius numeriais nuo 1 iki
. Tada, jei
kėlinio i
elemento numeris yra nelyginis skaičius, tai
prie io kėlinio priraykime element¹ n
i deinės ir nuosekliai atlikime visus galimus to elemento postūmius
į kairź. Jei kėlinio i
elemento numeris yra lyginis, tai prie jo
priraykime element¹ n i kairės
ir nuosekliai atlikime visus galimus to elemento postūmius į deinź.
Atlikź iuos veiksmus,
gausime kėlinių minimalaus pokyčio sek¹ (r. 3.4.2 pav.).
3.4.2 pav. Kėlinų generavimas minimalaus pokyčio tvarka
Aptartas
kėlinių minimalaus pokyčio sekos generavimo metodas neatitinka
aukčiau pateiktos kombinatorinių objektų generavimo algoritmo schemos:
skaičiavimo eigoje reikia saugoti visus kėlinius. Literatūroje [RND80]
pateikta io metodo realizacija, atitinkanti kombinatorinių objektų
generavimo algoritmo scem¹.
Aptarkime i¹ realizacij¹.
Įveskime tris
masyvus: ,
ir
.
Masyvo p elementai apibrė nagrinėjam¹
kėlinį. Elementai p0
ir pn+1 yra
pagalbiniai elementai.
Masyvo a elementai nusako atvirktinį
kėlinį: ak
nurodo viet¹ (adres¹), kurioje masyve p
yra elementas k. Kitaip tariant, . Masyvo d elementai apibrėiami taip:
Kėlinyje elementas i stumiamas iki jis pasiekia element¹, didesnį u jį patį. Tada yra keičiama io elemento judėjimo kryptis ir bandoma stumti (jei galima) element¹ i 1. Kadangi turime masyv¹ a, tai is elementas lengvai randamas masyve p.
Tam, kad nutrauktume
elemento n judėjim¹, į
masyv¹ p įvesti du papildomi
elementai ir
, kurių
reikmės yra lygios
.
Elemento reikmė yra lygi 0, nes p elemento, lygaus vienetui, judinti
nereikia. Tai sekos generavimo pabaigos s¹lyga.
begin
for i := 1 to n do begin
p [i] := i;
a [i] := i;
d [i] := 1;
end
d [1] := 0; p [0] := n + 1; p [n + 1] := n + 1; t := true;
while t do
begin
Spausdinti ();
m := n;
while p [a [m] + d [m]] > m do begin
d [m] := d [m];
m := m 1;
end
if m = 1 then t := false
else
begin
pp := p [a [m]];
p [a [m]] := p [a [m] + d [m]];
p [a [m] + d [m]] : =pp;
pp := a [m]; k := p [a [m]];
a [m] := a [k];
a [k] : =pp;
end
end
end
Kai , pateiktas
algoritmas apskaičiuoja:
Tarkime, kad bet koks kėlinys. Perskaičiuokime
į kėlinį pagal algoritm¹:
begin
for i := n downto 2 do
sukeisti p [i] su p [rand (1, i)],
čia rand k, l tolygiai pasiskirsčiusių atsitiktinių skaičių i atkarpos k, l generavimo procedūra
end
Taip gautas
kėlinys p su tikimybe gali sutapti su bet kuriuo kėliniu i
visų kėlinių aibės.
Tam, kad
įrodytume, jog visi kėliniai vienodai galimi, pasinaudokime
matematinės indukcijos metodu.
Kai akivaizdu.
Tarkime, kad algoritmas
generuoja atsitiktinį kėlinį, kai elementų skaičius yra . Tegu
yra bet kuris aibės
kėlinys. Tada tikimybė, kad
yra:
n-elementės
aibės X iskaidymas į k poaibių (blokų) tai
aibės X poaibių eima , kurios
elementai tenkina reikalavimus:
Poaibius vadinsime blokais.
Aibės X visų galimų iskaidymų
į k blokus aibź ymėsime , o
aibės X visų galimų
iskaidymų aibź ymėsime
. Aiku, kad
Su aibės X iskaidymu į blokus yra susijź Stirlingo ir Belo skaičiai.
Antrosios rūies Stirlingo
skaičius tai skirtingų n-elementės aibės iskaidymo į k blokus skaičius, t.y.
čia
.
Pavyzdiui, , kadangi
yra 7 skirtingi 4-ių elementų aibės
iskaidymo į du blokus būdai:
Akivaizdu, kad , kai
. Be to,
, kadangi
tučia blokų aibė sutinkamai su apibrėimu yra tučiosios
aibės iskaidymas.
Su antrosios rūies Stirlingo skaičiais, kaip ir su binominiais koeficientais, yra susijź daug tapatybių.
Pirmiausia įrodysime tapatybź, primenanči¹ derinių sudėties savybź, kuri yra susijusi su Paskalio trikampiu:
a) ,
,
b) ,
, (3.4.2)
c)
,
.
Formulių ir
teisingumas akivaizdus. 3.4.1 a) formulės
teisingum¹ įrodysime taip. Visus n-elementės
aibės iskaidymus į k
blokų suskirstykime į dvi klases. Pirmajai klasei priskirkime visus
iskaidymus, kuriuse yra vienelementinis blokas
, o antrajai
klasei priskirkime visus iskaidymus, kai elementas n yra didesnio bloko (maiausiai dviejų elementų
aibės) elementas.
Aiku, kad pirmosios
klasės galia yra , t.y.
tokia, kokia yra aibės
iskaidymo į
blokus galia.
Antrosios klasės
galia yra , kadangi
prie kiekvieno
iskaidymo į k blokus k skirtingais
būdais galima prijungti element¹ n:
elementas n paeiliui jungiamas prie
kiekvieno bloko.
(1.3.4) formulė
įgalina lengvai apskaičiuoti . emiau
pateikta
reikmių lentelė, primenanti
Paskalio trikampį.
i¹ lentelź galima
traktuoti kaip Stirlingo trikampį. i-osios
eilutės elementas yra lygus -osios
eilutės elemento i kairės ir
-osios
eilutės elemento i viraus, padauginto i k, sumai.
6 lentelė. Antrosios rūies Stirlingo skaičiai
n k | |||||||||||
Antrosios rūies
Stirlingo skaičiai yra susijź su n- osios
eilės polinomo , urayto
bazėje
, uraymu
bazėje
, čia
Teorema [Lip88]. Kiekvienam
Pavyzdiui, .
I tikro,
Pirmosios rūies Stirlingo
skaičiai. ie skaičiai
ymimi ir jie yra koeficientai prie x laipsnių daugianaryje
, t.y.
Kitaip tariant, skaičiai
vaidina atvirkči¹ vaidmenį atvilgiu
, t.y.
leidia polinom¹, urayt¹ bazėje
pervesti
į polinomo ura¹ bazėje
.
Nesunku parodyti
(palyginant koeficientus prie laipsnių lygybėje
), kad
tenkina s¹ryius:
,
,
,
, (3.4.3)
,
.
emiau pateikta pirmosios rūies Stirlingo skaičių lentelė.
7 lentelė. Pirmosios rūies Stirlingo skaičiai
n k | |||||||||||
|
Belo skaičius Bn. Belo skaičius tai visų galimų n-elementės aibės X iskaidymo į blokus skaičius:
, čia
.
Kitaip tariant,
Įrodysime Belo skaičius siejantį rekurentinį s¹ryį:
,
. (3.4.4)
Aibės visų galimų iskaidymų aibź
galima iskaidyti į klases, priklausomai nuo bloko B, turinčio savyje element¹
, arba, kas
ekvivalentu, priklausomai nuo aibės
. Kiekvienai
aibei
egzistuoja tiksliai
aibės X
iskaidymų, turinčių savyje blok¹ B.
Grupuodami klases priklausomai nuo aibės
galios, gauname (3.4.3) formulź.
emiau pateikta Belo skaičių lentelė.
8 lentelė. Belo skaičiai
n |
Bn |
Aptarsime n-elementės aibės visų galimų iskaidymų generavimo algoritm¹. io algoritmo idėj¹ lengviausia paaikinti suformulavus j¹ rekurentinėje formoje.
Aiku, kad kiekvienas
aibės iskaidymas p
vienareikmikai nusako aibės
iskaidym¹ pn ,
gaut¹ i iskaidymo p, kai i jo atitinkamo bloko paalinamas
elementas n (ir paalinamas tučiasis
blokas, jei elementas n sudarė
vienelementį blok¹).
Ir atvirkčiai, jei
turime aibės iskaidym¹
, tai lengva
rasti visus aibės
iskaidymus p, kad
, t.y.
(3.4.5)
i savybė
įgalina sudaryti paprast¹ rekurentinį metod¹, generuojantį visus
galimus aibės iskaidymus: jei mes inome aibės
visų galimų iskaidymų s¹ra¹ Ln-1, tai
visų galimų aibės
iskaidymų s¹raas Ln gaunamas pakeičiant kiekvien¹ s¹rao Ln-1 iskaidym¹ s (3.4.5) seka. Be to, nesunku pastebėti,
jei kas antram s¹rao s¹rao Ln-1
iskaidymui s invertuosime (raysime atvirkčia tvarka)
(3.4.5) sek¹, tai s¹rao Ln
gretimi iskaidymai maai skirsis vienas nuo kito. Tiksliau kalbant, kiekvienas
gretimas s¹rao Ln
iskaidymas bus gautas i prie jį esančio iskaidymo paalinant
kakokį element¹ i kakurio bloko ir patalpinant į element¹ į
kit¹ blok¹, arba sukuriant i jo vienelementinį blok¹. Pavyzdiui, jei
, tai
gausime tokius s¹raus:
Toliau aptarsime nerekurentinź io metodo realizacij¹.
Aibės iskaidymo blokus suraysime jų maiausio
elemento didėjimo tvarka. Bloko maiausi¹ element¹ mes vadinsime bloko
numeriu. Reikia paymėti, kad gretimų blokų numeriai bendru
atveju nėra i eilės ein¹ natūralieji skaičiai.
iame algoritme
naudosime kintamuosius ir
,
,
atitinkamai reikiančius prie ir po bloko, kurio numeris i, stovinčių blokų numerius. Jei blokas, kurio numeris i, yra paskutinysis iskaidymo blokas,
tai
.
Naudosime
kintam¹jį ,
. Jei
, tai
reikia, kad i-tasis aibės
elementas priklauso blokui, kurio numeris k.
Elemento judėjimo
kryptį nusakys kintamasis ,
. Jei
, tai
elementas i juda pirmyn.
emiau pateiktas algoritmas
generuoja visus galimus aibės iskaidymo
būdus, kai duotas aibės elementų skaičius n. Algoritmo rezultatas: visų galimų aibės
iskaidymų seka, kurioje kiekvienas
iskaidymas gaunamas i prie tai buvusio, perkeliant vienintelį element¹
į kit¹ blok¹.
begin
for i := 1 to n do
begin
blok [i] := 1; pirmyn [i] := true;
end
sek
Atspausdinti iskaidym¹
elementai, masyve blok paymėti tuo pačiu numeriu k,
priklauso k-ajam blokui.
j := n;
while j > 1 do
begin
k := blok [j];
if pirmyn [j] then
begin
if sek [k] := 0 then
begin
sek [k] := j; prec [j] := k; sek [j] := 0;
end
if sek [k] > j
begin
prec [j] := k;
sek [j] := sek [k];
prec [sek [j]] := j; sek [k] := j;
end
blok [j] := sek [k]
end
else
begin
blok [j] := prec [k];
if k = j then
if sek [k] = 0 then sek [prec [k]] := 0;
else
begin
sek [prec [k]] := sek [k];
prec [sek [k]] := prec [k];
end
end
Atspausdinti iskaidym¹.
j := n;
while ((j > 1) and ((pirmyn [j]) and (blok [j] = j))
or ((not pirmyn [j]) and (blok [j] := 1))) do
begin
pirmyn [j] := not pirmyn [j];
j := j 1;
end
end
end
Pateiktas algoritmas
pradioje generuoja iskaidym¹ , t.y.
pirm¹jį aibės iskaidym¹ s¹rae Ln,
kuris gaunamas aukčiau apraytu rekurentiniu metodu.
Pagrindinio ciklo while j > 1 do paskirtis yra aktyvaus elemento j radimas ir jo perkėlimas į kaimyninį blok¹, t.y. į blok¹ i deinės, jei pirmyn [j] turi reikmź true (iuo atveju gali būti sukuriamas blokas ), ir į blok¹ i kairės, jei pirmyn [j] = false.
I aukčiau pateikto rekurentinio metodo iplaukia, kad elementas j gali būti judinamas, kai visi didesni u jį elementai pasiekia savo ribinź kairi¹j¹ arba deini¹j¹ padėtį. Kitaip tariant, aktyvusis elementas j* yra toks elementas, kai visi didesni u jį elementai j (j > j*) tenkina vien¹ i dviejų s¹lygų:
a) pirmyn [j] and (blok [j] = j), t.y. elementas juda pirmyn (į deinź) ir pasiekia savo deini¹j¹ ribinź padėtį (aiku, kad j negali būti elementu bloko, kurio maiausias elementas yra didesnis u j);
b) not pirmyn [j] and (blok [j] = 1), t.y. elementas juda atgal (į kairź) ir pasiekia savo kairi¹j¹ ribinź padėtį.
Aiku, kad, jei elementas j tenkina vien¹ i minėtų s¹lygų, tai keičiama jo judėjimo kryptis.
Paanalizuokime aktyvaus elemento perkėlimo į kit¹ blok¹ proces¹.
Pirmiausia randamas numeris bloko, kuriame yra aktyvusis elementas. Tarkime, kad tokio bloko numeris yra k.
Jei aktyvusis
elementas juda į deinź, tai
pakanka perkelti jį į blok¹, kurio numeris yra , jei
ir
.
Jei arba
, tai
pirmiausia reikia modifikuoti
reikmź.
Tarkime, sek [k] . Vadinasi, aktyviojo elemento blokas yra
paskutinysis iskaidymo blokas. iuo atveju bus sudaromas naujas blokas . Tam tikslui pakanka priimti: ir atitinkamai pakeisti
ir
reikmes (r. algoritmo tekst¹).
Tarkime, sek [k] > j. Tai reikia, kad visi blokai, esantys deiniau bloko k, sudaryti i elementų, didesnių nei j (visi tie elementai uima ribinź deinź padėtį). Vadinasi, (r. rekurentinį metod¹), iuo atveju reikia sukurti vienelementį blok¹ . Tai ir įvykdoma (r. algoritmo tekst¹).
Situacijoje, kai aktyvusis elementas juda atgal (į kairź), pakanka patalpinti į element¹ į prie blok¹ k stovintį blok¹ ir atlikti atitinkamus masyvų sek ir prec elementų pakeitimus.
emiau surayti visi
galimi aibės iskaidymo būdai, apskaičiuoti pagal
aukčiau pateikt¹ algoritm¹.
Aiku, kad
iskaidymų skaičius yra
Nagrinėsime
natūraliojo skaičiaus n
iskaidym¹ į neneigiamų sveikųjų skaičių sek¹, kad
.
Jei skaičių tvarka sekoje
yra svarbi, tai toks skaičiaus n
iskaidymas vadinamas kompozicija. iuo atveju paprastai
įvedamas apribojimas:
,
.
Jei skaičių tvarka nesvarbi ir
, tai
yra multiaibė (aibė su
pasikartojančiais elementais) ir vadinama skaičiaus n iskaidymu.
Pavyzdiui, jei , tai (3),
(1, 2), (2, 1), (1, 1, 1) yra skaičiaus 3 kompozicija, o (3), (1, 2), (1, 1, 1)
iskaidymas.
Nagrinėjant kompozicij¹, į skaičių n patogu iūrėti kaip į atkarp¹, sudaryt¹ i vienetinio ilgio atkarpėlių, ir atkarpėlių susijungimo vietos paymėtos takais.
Pavyzdiui, kai ,
turėsime (r. 3.4.2 pav.).
3.4.2 pav. Grafinis kompozicijos (2, 1, 2, 2, 1) vaizdavimas
Tada kompozicijos
elementai yra atstumas tarp gretimų paymėtų takų. 3.4.2
pav. pavaizduota skaičiaus kompozicija (2, 1, 2, 2, 1). Aiku, kad
kiekvien¹ kompozicij¹ galima vaizduoti dvejetainiu skaičiumi, turinčiu
skiltį: vienetinė skiltis rodo
paymėt¹ tak¹. Pavyzdiui, kompozicijos
(2, 1, 2, 2, 1) kodas yra
.
n
skaičiaus kompozicija, susidedanti i k
dalių, atitinka -skiltį
dvejetainį skaičių, turintį
vienetuk¹, ir todėl egzistuoja
tokių kompozicijų.
Iskaidymas skiriasi
nuo kompozicijos tuo, kad komponentų tvarka nesvarbi. Pavyzdiui,
iskaidymo atveju nedarome skirtumo tarp tokių skaičiaus 4
iskaidymų: ,
,
.
Nagrinėjant skaičiaus n
iskaidym¹, patogu komponentes
idėstyti didėjimo tvarka, t.y.
.
Skaičiaus n iskaidym¹ į l komponentes patogu generuoti leksikografine tvarka, pradedant
iskaidymu ,
, ir tźsiant
proces¹ tokiu būdu: norėdami gauti leksikografikai didesnį
iskaidym¹ nei nagrinėjamas, nagrinėjame elementus i deinės
į kairź iki rasime pirm¹jį element¹
, tenkinantį
s¹lyg¹
; po to
keičiame
visiems
, ir
elementui pl suteikiame
reikmź
.
Pavyzdiui, jei ,
ir nagrinėjame iskaidym¹
, tai
gausime, kad pirmasis i deinės vienetukas tenkina s¹lyg¹
. Todėl
kitas iskaidymas bus
.
Jei nei vienas
iskaidymo elementas netenkina s¹lygos , tai
generavimo procedūra baigiama.
emiau pateikiamas aptarto metodo algoritmas.
begin
l
p [1] := n;
p
while l £ n do
begin
spausdinti
i := l 1;
while p [l] p [i] < 2 do i := i 1;
if i ¹ 0 then for j := i to l 1 do p [j] := p [i] + 1
else
begin
for j := 1 to l do p [j] := 1;
l := l + 1:
end
end
end
Skaičiaus n iskaidymo algoritm¹ galima i esmės pagerinti. Skaičiaus n iskaidym¹ galima urayti taip:
čia rodo, kad komponentė
į iskaidym¹ įeina
kartų, t.y.
Pasinaudojant tokiu
iskaidymo uraymu ir generuojant iskaidymus taip, kad , galima
gauti efektyvesnį iskaidymų generavimo algoritm¹ nei aukčiau
pateiktas.
Pavyzdiui, kai ,
generuodami iskaidymus nurodyta tvarka, gausime toki¹ iskaidymų sek¹:
emiau pateiktame
algoritme skaičiaus n iskaidym¹
pradėsime nuo iskaidymo .
Norėdami gauti nagrinėjamam iskaidymui
gretim¹ iskaidym¹, nagrinėsime patį
deinįjį iskaidymo element¹
.
Jei , tai
galime paalinti du elementus
ir įvesti dar vien¹ element¹
(arba įvesti vien¹ element¹
, jei tokio
elemento nagrinėjamu momentu nebuvo).
Jei , tai suma
pakankamai didelė, kad galėtume
įvesti dar vien¹
. Bet
kuriuo atveju tas, kas lieka, paverčiama į atitinkam¹ vienetukų
skaičių.
begin
l
p [1] := 0; m [1] := 0;
p [0] := n + 1;
m
p
m [1] := n;
while l ¹ 0 do
begin
spausdinti
sum := m [l] * p [l];
if m [l] = 1 then
begin
l := l 1
sum := sum + m [l] * p [l];
end
if p [l 1] = p [l] + 1 then
begin
l := l 1;
m [l] := m [l] + 1
end
else
begin
p [l] := p [l] + 1;
m [l] := 1;
end
if sum > p [l] then
begin
p [l + 1] := 1;
m [l + 1] := sum p [l];
l := l + 1
end
end
end
Aiku, kad pateiktas algoritmas yra tiesinis, kadangi skaičius operacijų, reikalingų pereinant nuo vieno iskaidymo prie kito, yra apribotas konstanta, nepriklausančia nei nuo n, nei nuo l.
Politica de confidentialitate | Termeni si conditii de utilizare |
Vizualizari: 2825
Importanta:
Termeni si conditii de utilizare | Contact
© SCRIGROUP 2025 . All rights reserved