Algoritmizálás Horváth Gyula Szegedi Tudományegyetem Természettudományi és Informatikai Kar horvath@inf.u-szeged.hu. Gráfos feladatok.. Feladat: Kiút keresés labirintusban. Egy négyzetrácsos hálózattal leírható labirintusban adott start helyről adott cél helyre kell eljutni a lehető legrövidebb úton. A labirintusban minden mező vagy fal, vagy közlekedésre használható folyosó egy részlete. Egy lépésben szomszédos mezőre léphetünk, balra, jobbra, felfelé vagy lefelé. 0 0. ábra.
0 0 0 Megoldás Modell: Tfh. a labirintus sorainak száma n, oszlopainak száma m. Tekintsük azt a G = (V,E) gráfot, ahol V = {(x,y) : x n y m (x,y)nem fal} (x,y) (x,y) E akkor és csak akkor, ha x x + y y = valamint (x,y) és (x,y) nem fal. Vagyis az (x,y) mezőről egyetlen lépéssel juthatunk az (x,y) mezőre. Tehát a feladat nem más, mint egy (Xk,Y k) (Xc,Xc) legrövidebb út keresése, ha a start mező (Xk,Y k) a célmező pedig (Xc,Xc). A feladat tehát megoldható szélességi kereséssel, a labirintus gráf számított-gráf ábrázolását használva. (x,y) (,0) (x,y ) (x,y) (x,y+) (0, ) (0,) (x+,y) (,0). ábra. A lehetséges lépések
program L a b i r i n t u s ; c o n s t MaxMN=00; { sorok és oszlopok max. száma } Lep : array [.. ] of record x, y :.. end={ a l é p é s e k e l ő r e } ( ( x : ; y : 0 ), ( x : 0 ; y : ), ( x : ; y : 0 ), ( x : 0 ; y : ) ) ; VLep : array [.. ] of record x, y :.. end={ a l é p é s e k v i s s z a } ( ( x : ; y : 0 ), ( x : 0 ; y : ), ( x : ; y : 0 ), ( x : 0 ; y : ) ) ; SorMeret=MaxMNΛMaxMN; type 0 Koord = 0..MaxMN; P o z i c i o =record x, y : Byte end ; L a b i r i n t =array [ 0.. MaxMN, 0..MaxMN] of i n t e g e r ; Sor=record Tar : array [.. SorMeret ] of P o z i c i o ; e l e j e, vege :Word end ; var M,N:Word; { a sorok és oszlopok száma } K:Word; { a f a l a k száma } Xk, Yk :..MaxMN; { a kezdő mező k o o r d i n á t á i } Xc, Yc :..MaxMN; { a c é l mező k o o r d i n á t á i } L: L a b i r i n t ; { a l a b i r i n t u s mátrixa } 0 S : Sor ; { Sor a bejáráshoz } x, y :Word; procedure Beolvas ; { Global : M, N, } var Bef : Text ; i, x, y :Word; begin Assign ( Bef, l a b i r i n t. be ) ; Reset ( Bef ) ; ReadLn ( Bef, M, N, K) ; 0 f o r x := to M do f o r y := to N do L[ x, y ] : = 0 ; ReadLn ( Bef, Xk, Yk, Xc, Yc ) ; f o r i := to K do begin ReadLn ( Bef, x, y ) ; L[ x, y ]:= ; end { f o r K} ; Close ( Bef ) ; end { Beolvas } ; 0 procedure S o r L e t e s i t ; begin S. e l e j e : = ; S. vege : = ; end { S o r L e t e s i t } ; procedure Sorba ( p : P o z i c i o ) ; begin S. Tar [ S. vege ] : = P ; Inc ( S. vege ) ; end { Sorba } ; procedure Sorbol ( Var p : P o z i c i o ) ; 0 begin p:=s. Tar [ S. e l e j e ] ; i n c ( S. e l e j e ) ; end { Sorbol } ; Function NemUres ( ) : Boolean ; begin NemUres:=S. e l e j e <S. vege ;
end { NemUres } ; procedure Bejar ( x, y : Koord ) ; { Global : Xc, Yc, L} 0 var i :Word; p, q : P o z i c i o ; begin { Bejar } S o r L e t e s i t ; p. x := x ; p. y := y ; Sorba ( p ) ; while NemUres Do begin Sorbol ( p ) ; i f ( p. x=xc ) And ( p. y=yc ) then Break ; { c é l b a értünk } 0 f o r i := to Do begin { l é p é s a négy l e h e t s é g e s szomszéd f e l é } q. x :=p. x+lep [ i ]. x ; q. y :=p. y+lep [ i ]. y ; i f L[ q. x, q. y ]=0 then begin { i t t még nem jártunk } L[ q. x, q. y ] : = i +; { a l é p é s b e j e g y z é s e } Sorba ( q ) ; {q t b e t e s s z ü k az a k t í v pontok sorába } end ; end { f o r i } ; end { while } ; end { Bejar } ; 0 procedure UtKiIro ; { Global : Xc, Yc, L} Var KiF : Text ; Ut : array [..MaxMN] of.. ; Tav, x, y, i : i n t e g e r ; begin Assign ( Kif, l a b i r i n t. ki ) ; Rewrite ( Kif ) ; i f L[ Xc, Yc] >0 then begin { van út a c é l b a } Tav : = 0 ; x :=Xc ; y :=Yc ; 0 while L[ x, y ] > do begin l e p e s :=L[ x, y ] ; x := x+vlep [ l e p e s ]. x ; y := y+vlep [ l e p e s ]. y ; i n c ( Tav ) ; Ut [ Tav ] : = l e p e s ; end { while } ; WriteLn ( Kif, Tav ) ; { az út hosszának k i í r a t á s a } f o r i := Tav downto do w r i t e ( KiF, Ut [ i ], ) ; 00 writeln ( KiF ) ; 0 end Else 0 WriteLn ( Kif, Nincs út ) ; 0 Close ( Kif ) ; 0 end { UtKiIro } ; 0 begin { Program } 0 Beolvas ; 0 0 f o r x := to M Do begin { i n i c i a l i z á l á s } 0 L[ x, 0 ] : = ; L[ x,m+]:= ; { k e r e t a t á b l a köré } 0 end ; f o r y := to N Do begin
L[ 0, y ] : = ; L[N+, y ]:= ; end ; L[Xk, Yk ] : = ; { a kezdőpontban már jártunk } Bejar (Xk, Yk ) ; UtKiIro ; end... Feladat: Mérőkannák Egy gazdának két kannája van, az egyik A literes, a másik pedig B. Szeretne kimérni pontosan L liter vizet. Az alábbi műveleteket lehet végezni a kimérés során:. Az A-literes kanna teletöltése. A B-literes kanna teletöltése. Az A-literes kanna kiürítése. A B-literes kanna kiürítése. Áttöltés az A-literesből a B-literesbe (amíg az tele nem lesz, ill. van A-ban). Áttöltés a B-literesből az A-literesbe (amíg az tele nem lesz, ill. van B-ben) Adjunk olyan algoritmust, amely meghatároz egy (legkevesebb lépésből álló) kimérést! Bemenet A kimer.be szöveges állomány első sora a két egész számot tartalmaz, a két kanna ürtartalmát: AB(0 < A,B <= 00). A második sor a kimérendő mennyiséget tartalmazza. Kimenet A kimer.ki szöveges állomány első sora a kimérés lépéseinek (minimális) m számát tartalmazza. A második sor pontosan m egész számot tartalmazzon egy-egy szóközzel elválasztva, a kimérés lépéseit. Példa bemenet és kimenet bemenet kimenet
kezdő állapot: (0,0) öntéssel kapható állapotok: (,0) (0,) öntéssel kapható állapotok: (,) (,) (,0) öntéssel kapható állapotok: (,0) (,) öntéssel kapható állapotok: (,) (,0) öntéssel kapható állapotok: (,0) (,) öntéssel kapható állapotok: (0,) (,) öntéssel kapható állapotok: (,) (0,) öntéssel kapható állapotok: (,) (,0) öntéssel kapható állapotok: (,0) (,) 0 öntéssel kapható állapotok: (,) (,0) öntéssel kapható állapotok: (,0) (,) öntéssel kapható állapotok: (0,) (,) Megoldás Minden állapot azonosítható egy (x, y) számpárral (0 x A, 0 y B). A kezdő állapot (0,0). Az öntögetés során tudnunk kell, hogy adott (x,y) állapotot elértük-e már? Továbbá, ha elő is kell állítani egy öntési sorrrendet, akkor most nem elég azt tudni, hogy egy állapot melyik lépéssel keletkezett. Valóban, pl. ha a (,) állapot az. lépéssel keletkezett, akkor az előző állapot lehetett (,),(,) vagy (,). Tehát minden elért állapothoz tároljuk azt az állapotot, amelyből keletkezett. Vegyünk egy EA tömböt, és EA[x, y].x = 0, ha az (x, y) állapotot még nem értük el, egyébkét az állapotot, amelyből keletkezett. program MeroKannak ; c o n s t MaxV=00; SorMeret =000; type A l l a p o t = record x, y : i n t e g e r end ; Sor=record e l e j e, vege :Word; Tar : array [.. SorMeret ] of A l l a p o t ; end ; 0 var A, B, L:Word; EA: array [ 0.. MaxV, 0.. MaxV] of A l l a p o t ; S : Sor ; procedure Sorba ( var S : Sor ; v : A l l a p o t ) ; begin S. Tar [ S. vege ] : = v ; Inc ( S. vege ) ; end ; procedure Sorbol ( var S : Sor ; var v : A l l a p o t ) ; 0 begin v :=S. Tar [ S. e l e j e ] ; Inc ( S. e l e j e ) ; end ; procedure Beolvas ; var BeF : Text ; begin Assign ( BeF, kimer. be ) ; Reset ( BeF ) ; ReadLn ( BeF, A, B ) ; ReadLn ( BeF, L ) ; 0 Close ( BeF ) ; end { Beolvas } ; procedure Szamit ;
var x, y :Word; U,V: A l l a p o t ; begin { } f o r x :=0 to A do f o r y :=0 to B do EA[ x, y ]. x:= ; S. e l e j e : = ; S. vege : = ; 0 EA[ 0, 0 ]. x : = 0 ; U. x : = 0 ; U. y : = 0 ; Sorba ( S,U) ; while ( S. e l e j e <S. Vege ) do begin Sorbol ( S,U) ; i f (U. x=l) t h e n break ; { kész, a kímérendő van a A kannában } i f EA[A,U. y ]. x<0 then begin {. l é p é s } V. x :=A; V. y :=U. y ; EA[V. x,v. y ] : =U; Sorba ( S,V) ; 0 end ; i f EA[U. x, B ]. x<0 then begin {. l é p é s } V. x :=U. x ; V. y :=B; EA[V. x,v. y ] : =U; Sorba ( S,V) ; end ; i f EA[ 0,U. y ]. x<0 then begin {. l é p é s } V. x : = 0 ; V. y := y ; EA[V. x,v. y ] : =U; Sorba ( S,V) ; end ; 0 i f EA[U. x, 0 ]. x<0 then begin {. l é p é s } V. x :=U. x ; V. y : = 0 ; EA[V. x,v. y ] : =U; Sorba ( S,V) ; end ; i f U. x+u. y<=b then begin { ö n t é s A ból B be } V. x : = 0 ; V. y :=U. x+u. y ; end e l s e begin V. x :=U. x (B U. y ) ; V. y :=B; end ; i f EA[V. x,v. y ]. x<0 then begin {. l é p é s } EA[V. x,v. y ] : =U; Sorba ( S,V) ; 0 end ; i f U. x+u. y<=a then begin { ö n t é s B ből A ba } V. y : = 0 ; V. x :=U. x+u. y ; end e l s e begin V. y :=U. y (A U. x ) ; V. x :=A; end ; i f EA[V. x,v. y ]. x<0 then begin {. l é p é s } EA[V. x,v. y ] : =U; Sorba ( S,V) ; end ; end { while az S sor nem üres } ; 0 end { Szamit } ; procedure KiIr ; c o n s t maxa=0000; var KiF : Text ; x, y,m, i, l e p e s : i n t e g e r ; Lehet : boolean ; szep : s t r i n g ; U,V: A l l a p o t ;
Lepsor : array [.. MaxA] of A l l a p o t ; 0 begin Assign ( KiF, kimer. ki ) ; Rewrite ( KiF ) ; l e h e t := f a l s e ; f o r y :=0 to B do i f EA[L, y ]. x>0 then begin l e h e t := t rue ; U. y := y ; break ; end ; i f not l e h e t then begin w r i t e l n ( KiF, 0 ) ; c l o s e ( KiF ) ; e x i t ; 00 end ; 0 U. x :=L; m: = 0 ; 0 while (U. x < >0) or (U. y < >0) do begin 0 i n c (m) ; 0 LepSor [m] : =U; 0 U:=EA[U. x,u. y ] ; 0 end ; 0 U. x : = 0 ; U. y : = 0 ; 0 w r i t e l n ( KiF,m) ; 0 szep := ; 0 f o r i :=m downto do begin V:= LepSor [ i ] ; i f (V. x=a) and (U. y=v. y ) then begin l e p e s : = ; end e l s e i f (U. x=v. x ) and (V. y=b) then begin l e p e s : = ; end e l s e i f (V. x =0) and (U. y=v. y ) then begin l e p e s : = ; end e l s e i f (U. x=v. x ) and (V. y =0) then begin l e p e s : = ; 0 end e l s e i f (V. x =0) and (V. y=u. x+u. y ) or (V. x=u. x (B U. y ) ) and (V. y=b) then begin l e p e s : = ; end e l s e begin l e p e s : = ; end ; w r i t e ( KiF, szep, l e p e s ) ; szep := ; U: =V; end { f o r i } ; w r i t e l n ( KiF ) ; Close ( KiF ) ; 0 end { KiIr } ; begin Beolvas ; Szamit ; KiIr ; end... Gráf adattípus, gráfok ábrázolása... Definíciók. Irányítatlan gráf:g = (V, E) E rendezetlen {a, b}, a, b V párok halmaza.. Irányított gráf:g = (V, E) E rendezett (a, b) párok halmaza; E V V.. Multigráf:
. ábra. Példa gráf G = (V,E,Ind,Érk), Ind,Érk : E V Ind(e) az e él induló, Érk(e) az érkező pontja. Címkézett (súlyozott) gráf:g = (V, E,C) C : E Címke Minden irányítatlan G = (V, E) gráf olyan irányított gráfnak tekinthető, amelyre teljesül, hogy ( p, q V )((p, q) E (q, p) E). Jelölések KiEl(G, p) = {q V : (p,q) E} BeEl(G, p) = {q V : (q, p) E} KiFok(G, p) = Ki(G, p) BeFok(G, p) = Be(G, p)... Műveletek gráfokon A továbbiakban feltételezzük, hogy a gráf pontjait természetes számokkal azonosítjuk, pontosabban V {,...,n} Milyen műveleteket akarunk gráfokon végezni? Pontokszama Elekszama KiFok(p) BeFok(p) PontBovit(p) PontTorol(p) ElBovit(p, q) ElTorol(p, q) VanEl(p, q) for q in KiEl(p) do M(p,q)... Gráfok ábrázolásai Szempontok az adatszerkezet megválasztásához.. Az adott probléma megoldásához ténylegesen mely műveletek szükségesek.. Melyek a releváns műveletek, amelyek alapvetően befolyásolják az algoritmus futási idejét.. A tárigény az adott probléma esetén.
. ábra. Példa gráf Graf.txt Éltömb Éllánc 0 0 ESz=... ábra. Élhalmaztömb és élhalmazlánc 0
. Élhalmaztömb és élhalmazlánc. Kapcsolatmátrix (szomszédsági mátrix) G. ábra. Kapcsolatmátrix c o n s t maxp=000; / / a pontok max. száma type Graf=array [.. maxp,.. maxp ] of boolean ; CGraf=array [.. maxp,.. maxp ] of i n t e g e r ; (p,q) akkor és csak akkor éle a gráfnak, ha G[p,q] = true. Címkézett gráf esetén választani kell egy nem Cimke értéket, amely nem fordul elő semmilyen él címkéjeként. (p, q) akkor és csak akkor éle a címkézett gráfnak, ha G[p,q]! = nem, és a (p,q) él címkéjének értéke G[p,q].. Élhalmaz-tömb G 0 0 0 0 0 0 KiFok 0 0 0 0. ábra. Gráf ábrázolása élhalmaz-tömbbel c o n s t maxp=000; / / a pontok max. száma type Graf=array [.. naxp, maxp ] of i n t e g e r ; KiFok=array [.. naxp ] of i n t e g e r ; A Ki(G, p) halmaz bejárása:
f o r i := to KiFok [ p ] do begin q:=g[ p, i ] ; M( p, q ) ; end ;. Élhalmaz-lánc........... ábra. Gráf ábrázolása élhalmaz-lánccal a.) Statikus élhalmaz-lánc c o n s t maxp=000; / / a pontok max száma maxe=00000; / / az é l e k max. száma type Lanc= l o n g i n t ; C e l l a =record pont. i n t e g e r ; c s a t : Lanc end ; Graf=array [.. naxp ] of Lanc ; Elek : array [.. maxe] of C e l l a ; b.) Dinamikus élhalmaz-lánc c o n s t maxp=000; type Lanc=^ C e l l a ; C e l l a =record pont. i n t e g e r ; c s a t : Lanc end ; Graf=array [.. naxp ] of Lanc ;. Számított gráf Az élek halmazát explicite nem tároljuk, mert van olyan számítási eljárás, amely bármely két p, q V -re kiszámítja VanEl(p, q)-t.
Vagy, van olyan számítási eljárás, amely minden p V -re kigenerálja a Ki(G, p) halmaz elemeit... Elemi gráfalgoritmusok... Utak Legyen G = (V,E) irányított (irányítatlan) gráf... definíció. p,q V -re egy p-ből q-ba vezető út G-ben, jele: π : p q, olyan π = p 0, p,, p k pontsorozat, ahol p i p j, ha i j, p = p 0 és q = p k, továbbá p = q = p 0, vagy ( i {,...,k}) ((p i, p i ) E)... definíció. A π = p q út hossza, π = p q = k.. definíció. p-ből q-ba vezető legrövidebb út hossza, p és q távolsága: { ha nincs p q δ(p,q) = Min{ π : p q } π : p q ().. definíció. A π = p 0, p,, p k pontsorozatot a p 0 -ból p k -ba vezető sétának nevezzük, ha ( i {,...,k})(p i, p i ) E.. definíció. Ha G = (V,E,C) élei a C : E R függvénnyel súlyozottak, akkor a p q út hossza p q = k i= C(p i, p i ). A p és q pont távolsága: { δ(p,q) = Min{ π : p q } ha nincs p q π : p q ().. definíció. A G = (V,E) (irányítatlan) gráfnak az F = (V,E) gráf a r V gyökerű feszítőfája, ha. F részgráfja G-nek (V V,E E,) és fa.. ( p V ) ha van r p G-ben, akkor és csak akkor, ha van r p F-ben... definíció. A G = (V,E) (irányítatlan, súlyozott) gráfnak az F = (V,E) gráf a r V gyökerű legrövidebb utak feszítőfája (LUF), ha. F r-gyökerű feszítőfája G-nek, és. p V -ra δ G (r, p) = δ F (r, p). Útproblémák. Adott p,q V -re van-e p q út?. Adott p-re az Elr(p) = {q : p q} halmaz kiszámítása.. Adott p,q V -re δ(p,q) és egy p q legrövidebb út kiszámítása.. Egy pontból induló legrövidebb utak : adott p-re minden q-ra δ(p,q) és egy p q legrövidebb út kiszámítása.. Minden p,q pontpárra δ(p,q) és egy p q legrövidebb út kiszámítása.
... Szélességi keresés Bemenet: G = (V,E) (irányított vagy irányítatlan) gráf és egy r V pont. Kimenet: D : V N, Apa : V V, hogy D(p) = δ(r, p) és az F = (V,E) gráf, ahol V = {p : Apa(p) null p = r}, E = {(p,q) : Apa(q) = p p null} r-gyökerű LUF. procedure S z e l t B e j a r ( p : PontTip ) ; / / p ből induló l e g r ö v i d e b b utak meghatározása { Global :G, N, D, Apa } var S : SorTip ; u, v : PontTip ; i :Word; begin { S z e l t B e j a r } f o r u:= to N do D[ u ] : = I n f ; { i n i c i a l i z á l á s } 0 D[ p ] : = 0 ; Apa [ p ] : = 0 ; U r e s i t ( S ) ; Sorba ( S, p ) ; while NemUres ( S ) do begin SorBol ( S, u ) ; f o r i := To KiFok [ u ] Do Begin { u > v é l r e } v :=G[ u, i ] ; i f D[ v ]= I n f then begin { ha v meg nem e l é r t } Apa [ v ] : = u ; 0 D[ v ] : =D[ u ] + ; Sorba ( S, v ) ; end ; end { f o r u >v } ; end { while } ; end { S z e l t B e j a r } ;... Mélységi keresés procedure MelyBejar ( p : PontTip ) ; / / p ből e l é r h e t ő pontok meghatározása { Global :G, N, Apa } var q : PontTip ; i :Word; begin { MelyBejar } f o r i := To KiFok [ p ] Do Begin { p > q é l r e } q:=g[ u, i ] ; 0 i f Apa [ q] <0 then begin { ha q meg nem e l é r t } Apa [ q ] : = p ; MelyBejar ( q ) ; end ; end { f o r p >q} ; end { MelyBejar } ;.. Feladat: Terv Egy nagyszabású építkezés terve n különböző munka elvégzését írja elő. Minden munkát egy nap alatt lehet elvégezni. Egy napon több munkát is el lehet végezni párhuzamosan, feltéve, hogy a megelőzési feltételt betartjuk. Ez ezt jelenti, hogy vannak olyan
előírások, hogy egy adott a munka elvégzése meg kell, hogy előzze más adott b munka elégzését. Tehát a b munkát csak akkor lehet elkezdeni, ha már az a munkát befejeztük. Kiszámítandó, hogy a teljes építkezést legkevesebb hány nap alatt lehet befejezni! Bemenet A terv.be szöveges állomány első sora két egész számot tartalmaz, az elvégzendő munkák n számát ( n 00), és a megelőzési előírások m számát (0 m 0000). Kimenet A terv.ki szöveges állomány első sora az összes munka elvégzéséhez szükséges napok k számát tartalmazza. Ha a megelőzési előírások miatt nem lehet elvégezni az összes munkát, akkor az első ás egyetlen sorba a 0 számot kell írni. A további k sor mindegyike egy napon elvégzendő munkák sorszámait tartalmazza egy-egy szóközzel elválasztva. Példa bemenet és kimenet bemenet 0 0 0 0 kimenet 0 0. ábra. A példa bemenet ábrája. Megoldás Elvi algoritmus. Legyen G = (V,E) az a gráf, amelynek pontjai a munkák és élei a megelőzési feltételek. M := {v V : BeFok(v) = 0}; {az első napi munkák } while (M /0) and (V /0 )do begin
KiIr(M ); V := V M ; töröljük az E élekből minden olyan p q élet, amelyre p M ; M := {v V : BeFok(v) = 0}; end Akkor és csak akkor van megoldás, ha a megelőzési feltétel nem tartalmaz kört. Hogyan deríthető ez ki a fenti algoritmus során? Ha van kör, akkor a fenti algoritmusban az ismétlés úgy ér véget, hogy M = /0 de V /0. Fordítva is igaz, tehát ha az ismétlés úgy ér véget, hogy utána V /0, akkor van kör, mert nincs 0-befokú pont a megmaradtak között. Tehát elég megszámolni, hogy hány pont kerül bele az M halmazokba. A megelőzési előírások (gráfjának) ábrázolása. Milyen műveleteket kell végezni? Adott u-ra (hatékonyan) meg kell tudni adni mindazon v-ket, amelyeket u megelőz. Jelölje ezek halmazát Ki[u]. Vegyünk egy G tömböt, amelynek G[u] eleme olyan lánc fejére mutat, amely lánc a Ki[u] halmaz elemeit tartalmazza. G 0 0 0 0. ábra. A példa megelőzési előírásainak ábrázolása láncokban. program Terv ; c o n s t MaxN=0000; type Pont =..MaxN; Lanc=^ C e l l a ; C e l l a =record oda : Pont ; c s a t : Lanc end ; Graf=array [.. MaxN] of Lanc ; var 0 N,M: Word; G: Graf ; Beoszt : array [.. ΛMaxN] of 0.. MaxN;
BeFok : array [.. MaxN] of 0.. MaxN; Nap :Word; procedure Beolvas ; var BeF : Text ; i, u, v : i n t e g e r ; Guv: Lanc ; 0 begin Assign ( BeF, t e r v. be ) ; Reset ( BeF ) ; ReadLn ( BeF, N, M) ; f o r u:= to N do begin G[ u ] : = N i l ; Befok [ u ] : = 0 ; end ; f o r i := to M do begin Readln ( BeF, u, v ) ; 0 New(Guv ) ; { új c e l a l é t e s í t é s e } Guv^. oda := v ; { az u >v é l f e l v é t e l e a láncba : } Guv^. c s a t :=G[ u ] ; { a Guv c e l l a bekapcsolása a G[ u] lánc e l e j é r e } G[ u ] : = Guv; end { f o r i } ; Close ( BeF ) ; end { Beolvas } ; procedure Szamit ; var 0 i, e l e j e, vege, p, q :Word; El : Lanc ; begin Nap : = 0 ; vege : = 0 ; f o r i := to N do { a 0 megelőzöjüek halmazának k i s z á m í t á s a } i f Befok [ i ]=0 then begin Inc ( vege ) ; Beoszt [ vege ] : = i ; end ; Inc ( vege ) ; 0 Beoszt [ vege ] : = 0 ; e l e j e : = ; while True do begin Inc ( Nap ) ; while Beoszt [ e l e j e ]<>0 do begin p:= Beoszt [ e l e j e ] ; Inc ( e l e j e ) ; El :=G[ p ] ; while El <> n i l do begin { a p >q é l e k f e l d o l g o z á s a } q:= El ^. oda ; El := El ^. c s a t ; 0 Dec ( BeFok [ q ] ) ; i f BeFok [ q]=0 then begin { q f e l v é t e l e az akt. napra } Inc ( vege ) ; Beoszt [ vege ] : = q ; end ; end { while El } ; end { while e l e j e } ; i f vege= e l e j e then Break ;
Inc ( vege ) ; Beoszt [ vege ] : = 0 ; 0 Inc ( e l e j e ) ; end { while } ; end { Szamit } ; procedure KiIr ; var i, ind :Word; KiF : Text ; begin Assign ( KiF, t e r v. ki ) ; Rewrite ( KiF ) ; i f Jok<>N then Nap : = 0 ; WriteLn ( KiF, Nap ) ; 0 ind : = ; f o r i := to Nap do begin r epeat Write ( KiF, Beoszt [ ind ], ) ; Inc ( ind ) u n t i l Beoszt [ ind ] = 0 ; Inc ( ind ) ; WriteLn ( KiF ) ; end { f o r i } ; Close ( KiF ) ; 0 end { KiIr } ; begin { Program } Beolvas ; Szamit ; KiIr ; end... Feladat: Első Képtárlátogatás Egy sok teremből álló képtárban teszünk látogatást. Tudjuk, hogy a főbejárattól a képtár bármely termébe pontosan egy útvonalon keresztül lehet eljutni. Adjunk olyan bejárási stratégiát, amely biztosítja, hogy minden terembe eljutunk (minden képet pontosan egyszer nézünk meg)! 0. ábra. Egy képtár alaprajza
Megoldás A fal mellett mindig jobbra haladjunk. A lényeg, hogy adott teremből közvetlenül melyik termekbe tudok átmenni. Az alaprajz 0. ábra. ábráján kössük össze egyenes szakasszal az olyan teremsorszám-párokat, amelyek között van ajtó (tehát közvetlenül át lehet menni egyikből a másikba)... Feladat: Második Képtárlátogatás Ha a képtár nem teljesíti azt a feltételt, hogy bármely két terem között pontosan egy útvonal létezik (a gráfja fa), akkor nem alkalmazható a "fal mellett mindig jobbra" el. Az ábrán látható képtár esetén a. terembe nem jutnánk el. Fogalmazzuk meg pontosan a megoldandó feladatot. Bemenetként adott egy képtár termeinek leírása, amely tartalmazza minden teremre, hogy abból közvetlenül melyik termekbe lehet átmenni. Feltesszük, hogy n terem esetén a termeket az,..., n számokkal azonosítjuk, a bejáratot tartalmazó terem azonosítója. A kimenet a termek sorszámaiból álló olyan a,a,,a m számsorozat, amely megadja, hogy a bejárattól indulva milyen sorrendben kell haladnunk a képtárban, hogy minden terembe eljussunk, és a sétát a bejáratot tartalmazó. teremben fejezzük be. Tehát a,a,,a m számsorozatra az alábbiak teljesülnek: a = és a m = Minden i-re az a i teremből van ajtó az a i+ terembe ( i < m). Minden és n közötti szám legalább egyszer előfordul a sorozatban. Bemenet A keptar.be szöveges állomány első sora a termek n ( n 00)számát tartalmazza. A következő n sor mindegyike egy terem szomszédos termeit adja meg. Az i + -edik sorban azon termek sorszámai vannak felsorolva (egy-egy szóközzel elválasztva) 0-val zárva, amelyekbe nyílik ajtó az i-edik teremből. Kimenet A keptar.ki szöveges állomány egy megoldást tartalmazzon. Több megoldás esetén bármelyik megadható.
0. ábra. 0. ábra. 0
0. ábra. A "fal mellett mindig jobbra" elv alkalmazása.. ábra.
Példa bemenet és kimenet bemenet 0 0 0 0 0 0 0 0 0 kimenet Megoldás Mit kell tudnunk?. Jártunk-e már az adott teremben?. Melyik teremből léptünk először az adott terembe? Minden p teremre Honnan(p) legyen annak a teremnek a száma, amelyből először lépünk a p terembe. Kezdetben legyen minden p-re Honnan(p) = 0. Így ha a p teremben vagyunk, és a q terembe vezet ajtó, a Honnan(q) értéke alapján el tudjuk dönteni, hogy jártunk-e q-ban.
Az algoritmus: at = ; / / az a k t u á l i s terem Honnan ( ) = ; / / az u t c á r ó l léptünk a f ő b e j á r a t termébe while ( at!= ) do begin / / amíg v i s s z a nem értünk a b e j á r a t / k i j á r a t h o z i f ( at nek van q benemjárt szomszédos terme ) then begin Honnan ( q ) = at ; at = q ; end e l s e at = Honnan ( at ) ; end program Keptar ; c o n s t MaxN=00; var N, i, at : i n t e g e r ; G: array [.. MaxN,.. MaxN] of i n t e g e r ; Honnan, Ki, Fok : array [.. MaxN] of i n t e g e r ; KiF : Text ; procedure BeOlvas ; 0 var i, x, y : i n t e g e r ; BeF : Text ; begin Assign ( BeF, keptar. be ) ; Reset ( BeF ) ; ReadLn ( BeF,N) ; f o r i := to n do begin Fok [ i ] : = 0 ; Read ( BeF, x ) ; while ( x < >0) do begin i n c ( Fok [ i ] ) ; 0 G[ i, Fok [ i ] ] : = x ; read ( BeF, x ) ; end ; end ; Close ( BeF ) ; end { Beolvas } ; begin { Program } Beolvas ; Assign ( KiF, keptar. ki ) ; Rewrite ( KiF ) ; f o r i := to n do begin 0 Honnan [ i ] : = 0 ; Ki [ i ] : = 0 ; end ; at : = ; Honnan []:= ; while at >0 do begin w r i t e ( KiF, at, ) ; r epeat i n c ( Ki [ at ] ) ; u n t i l ( Ki [ at ] >Fok [ at ] ) or ( Honnan [G[ at, Ki [ at ] ] ] = 0 ) ; 0 i f Ki [ at ] <=Fok [ at ] then begin Honnan [G[ at, Ki [ at ] ] ] : = at ; at :=G[ at, Ki [ at ] ] ; end e l s e at :=Honnan [ at ] ; end { while } ;
c l o s e ( KiF ) ; end.. ábra.. ábra. A képtár gráfja. ábra. Egy teljes körséta:. A p Honnan[p] élek egy feszítőfát adnak. Rekurzív megvalósítás program Keptar ; c o n s t MaxN=00; var N,M:Word; G: array [.. MaxN,.. MaxN] of i n t e g e r ; Apa, Fok : array [.. MaxN] of i n t e g e r ; i : i n t e g e r ; KiF : Text ;
0 procedure BeOlvas ; var i, x, y : i n t e g e r ; BeF : Text ; begin Assign ( BeF, keptar. be ) ; Reset ( BeF ) ; ReadLn ( BeF,N) ; f o r i := to n do begin Fok [ i ] : = 0 ; Read ( BeF, x ) ; while ( x < >0) do begin 0 i n c ( Fok [ i ] ) ; G[ i, Fok [ i ] ] : = x ; read ( BeF, x ) ; end ; end ; Close ( BeF ) ; end { Beolvas } ; procedure MelyBejar ( p : i n t e g e r ) ; { Global : G, Fok, Apa} var 0 i, q : i n t e g e r ; begin f o r i := to Fok [ p ] do begin q:=g[ p, i ] ; i f Apa [ q] <0 then begin {q ban még nem jártunk } Apa [ q ] : = p ; {p ből j ö t t ü n k q ba } w r i t e ( KiF,, q ) ; { átlépünk q ba } MelyBejar ( q ) ; {q ból e l é r h e t ő k b e j á r á s a } w r i t e ( KiF,, p ) ; { v i s s z a k e l l menni p be } end ; 0 end { f o r i } ; end { MelyBejar } ; begin { Program } Beolvas ; Assign ( KiF, keptar. ki ) ; Rewrite ( KiF ) ; f o r i := to n do begin Apa [ i ]:= ; end ; Apa [ ] : = 0 ; w r i t e ( KiF, ) ; 0 MelyBejar ( ) ; c l o s e ( KiF ) ; end... Feladat: Iskolahálózat (IOI ) Néhány iskola számítógépes hálózatba van kötve. Az iskolák a szabadon terjeszthető programok elosztására megállapodást kötöttek: minden iskola egy listát vezet azokról az iskolákról ("szomszédairól"), amelyek számára a programokat továbbküldi. Megjegyzés: ha B iskola szerepel az A iskola terjesztési listáján, akkor A nem feltétlenül szerepel B terjesztési listáján. Írjon programot, amely meghatározza azt a legkisebb számot, ahány iskolához egy új programot el kell juttatni ahhoz, hogy - a megállapodás alapján, a hálózaton keresztül terjesztve - végül minden iskolába eljusson. Bemenet Az INPUT.TXT állomány első sora egy egész számot, a hálózatba kapcsolt iskolák n számát tartalmazza ( n 00). Az iskolákat az első n pozitív egész számmal azonosítjuk. A következő n sor mindegyike egy-egy terjesztési listát ír le. Az i + -edik
sor az i-edik iskola terjesztési listáján szereplő iskolák azonosítóit tartalmazza. Minden lista végén egy 0 szám áll. Az üres lista csak egy 0 számból áll. Kimenet A program az eredményt, amely két sorból áll, az OUTPUT.TXT nevű fájlba kell írja. Az első sor egy pozitív egész számot, azt a legkisebb m számot, ahány iskolához egy új programot el kell juttatni ahhoz, hogy - a megállapodás alapján, a hálózaton keresztül terjesztve - végül minden iskolába eljusson. A második sorban kell megadni az m kiválasztott iskolát, egy-egy szóközzel elválasztva. Példa bemenet és kimenet bemenet 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 kimenet Megoldás Jelölje G = (V,E); V = {,...,n} az iskolahálózat gráfját. Legyen D V egy megoldáshalmaz, tehát ( q V )( p D)(p q) A D halmazt lépésenként építhetjük: Adott p V pontra jelölje Eler(p) a p pontból elérhető pontok halmazát: Eler(p) = {q : p q} Terjesszük ki ezt halmazokra: Eler(D) = p DEler(p) begin D := /0; DbolElert := /0; for p V do if p / DbolElert then begin D := D Eler(p) {p} DbolElert := DbolElert Eler(p) end end Az Eler(p) halmaz elemei mélységi bejárással kiszámíthatók. Az algoritmus futási ideje legrosszabb esetben O(n ). Az algoritmus legrosszabb esete, ha a bemenetben p szomszédai: {,,..., p }. Ha n 000 is lehet, akkor ez az algoritmus biztosan nem elég gyors megoldás. Gyorsítási ötlet: elsőször rakjuk a pontokat olyan sorrendbe, hogy ha p q, de nincs q p, akkor p előbb álljon a sorozatban, mint q.
0 0. ábra. 0. ábra.
Egy ilyen kívánt sorrendet egyetlen mélységi bejárással előállíthatunk: a p pontra hívott (rekurzív) mélységi bejárásban, miután p-ből kiinduló összes élet bejártunk, rakjuk p-t a sorozat elejére. (Tehát a kívánt sorozatban a pontok elhagyási idő szerint csökkenő sorrendben lesznek.) Az így módosított algoritmus két mélységi bejárást végez, tehát futási ideje O(E) 0 ET 0 0 El() El() El() El(). ábra. A hálózat ábrázolása. A p iskola szomszédjainak listája a ET tömb El[p],..., El[p + ] indexű elemeiben vannak. program Halozat ; c o n s t maxn=000; { a pontok maximális száma } maxe=00000; { az é l e k maximális száma } type Pont =.. maxn; P a l e t t a =( Feher, Szurke, Fekete ) ; var ET: array [.. maxe] of 0.. MaxN; 0 El : array [.. MaxN+] of l o n g i n t ; N: Longint ; { a pontok száma } Szin : array [.. maxn] of P a l e t t a ; Ver : array [.. maxn] of Pont ; { verem } Vm: Longint ; { verem mutató } D: array [.. MaxN] of Pont ; DSzam: I n t e g e r ; procedure BeOlvas ; var i, p, q :Word; BeF : Text ; begin Assign ( BeF, h a l o z a t. be ) ; Reset ( BeF ) ; ReadLn ( BeF,N) ; El [ ] : = ; i : = ; f o r p:= to N do begin Read ( BeF, q ) ; 0 while q<>0 do begin ET[ i ] : = q ; i n c ( i ) ; Read ( BeF, q ) ; end ; readln ( BeF ) ; El [ p +]:= i ; end ; Close ( BeF ) ; end { Beolvas } ; Procedure MelyBejar ( u : Pont ; e l s o : boolean ) ; { Global : G, Szin, Ver } Var i, v : l o n g i n t ; begin Szin [ u ] : = Szurke ;