Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Алгоритмдеу жане багдарламалау негиздери 4 г.doc
Скачиваний:
3
Добавлен:
01.07.2025
Размер:
2.73 Mб
Скачать

26 Дәріс тақырыбы: Қайталанбалы алгоритм. Аттың жүрісі туралы есеп.

Нақтылаудың тағы бір қадамын жасасақ программалаудың негізгі тілінің терминдерінде толық жазылған программаны аламыз. Бұған дейін программа аттың қозғалысын басқаратын ережелерге мүлде тәуелсіз жасалды. Біз есептің жеке ерекшеліктерін қарауды әдейі кейінге қалдырып отырдық. Енді оларға назар аударатын уақыт келді.

3

2

4

1

К

5

8

6

7

Сурет. Аттың сегіз мүмкін жолдары.

Егер х, у координатының бастапқы жұбы берілген болса, онда келесі v жүрісі үшін сегіз мүмкін кандидаттар бар. Суретте олар 1-ден 8-ге дейін нөмірленген. Х-тен и v алу өте оңай, соңғысына айырымдардың жиымында сақталынған немесе жеке айырымдар сақталатын екі жиымда сақталынатын координаттар арасындағы айырымды қосса жеткілікті. Осы жиымдарды dx және dy арқылы белгілейміз және олар тиісінше инициализацияланған деп есептейміз. Кезекті жүріс-кандидатты нөмірлеу үшін к индексін пайдалануға болады. Толық листингте көрсетілген. Бірінші рет рекурсивті процедураға айналу басталатын өріс координаттары - х0 және у0 өлшемдерімен қарайды.

Листинг. Өрісті аттың жүрісімен айналып шығу.

PROGRAM KnightsTour;

USES InOut;

VAR i.j.n, Nsqr: INTEGER; q: BOOLEAN;

dx.dy: ARRAY [1..8] OF INTEGER;

h: ARRAY [1..8, 1..8] OF INTEGER;

PROCEDURE Try(i,x,y: INTEGER; VAR q: BOOLEAN);

VAR k, u, v: INTEGER; q1: BOOLEAN;

BEGIN k := 0;

REPEAT k ;= k+1; q1 := FALSE;

u :- x + dx[k]; v := у + dy[k];

IF (1 <= u) and (u <= n) and (1 <= v) and (v <=n) and (h[u,v] =0)

THEN BEGIN h[u, v] := i;

IF i < Nsqr THEN Try(i+1, u, v, q1);

IF not q1 THEN h[u,v] := 0

ELSE q1 := TRUE

END

UNTIL q1 OR (k = 8);

q := q1

END; {Try}

BEGIN

dx[1]

:=2; dx[2]

:= 1; dx[3]

:= -1; dx[4]

:= -2;

dx[5]

:= -2; dx[6]

:= -1; dx[7]

:= 1; dx[8]

:= 2,

dy[1]

:= 1: dy[2]

:= 2; dy[3]

:= 2; dy[4]

:= 1;

dy[5]

:= -1; dy[6]

:= -2; dy[7]

:= -2; dy[8]

:= -1;

WHILE true DO BEGIN

Readlnt(n);

IF not Done THEN EXIT; (* циклдан шығу *)

FOR i := 1 TO n DO

FOR j :=1 TO n DO h[i,j] := 0;

Readlnt(i); Readlnt(j); WriteLn;

Nsqr := n*n; h[1,1] ;= 1;

Try(2,i,j,q);

IF q THEN

FOR i := 1 TO n DO BEGIN

FOR j := 1 TO n DO Writelnt(h[i,j]:5);

WriteLn

END

ELSE WriteString ('no path'); WriteLn

END

END {KnightsTour}

Бұл өріске 1 мәні берілуі тиіс, қалған өріс бос ретінде маркіленеді:

h [х0,.у0]:= 1; Try(2, x0, y0, q);

Тағы бір детальды қалдырып кетуге болмайды. һ айнымалысы егер и и және v 1…п индекстер диапазонында жатқан жағдайда ғана бар болады. Демек, аяқталудың орнына қойылған в өрнегі, егер оның алғашқы төрт құрауышы ақиқат болса ғана түсінікті болады. Сондықтан huv =0 құрауышы соңғы болуы маңызды. Кестеде n=5 болғанда <3,3> және <2,4> мен n=6 болғанда <1,1> үш бастапқы позициясы үшін шешім келтіріледі.

Осы мысалдан қандай қорытынды жасауға болады? Онда біз қандай схемаға сүйендік, ол шешімді іздеу алгоритмдері үшін әдеттегі бола ма? Бұл мысал бізді неге үйретті? Мұндай алгоритмдердің өзіне тән қасиеті оларда жалпы шешімнің бағытында қадам жасалатынында жатыр, бірақ олардың бәрі кейін кері келуге болатындай түрде белгіленеді (жазылады). Мұндай процесс қайтару немесе шегіну (backtracking) деп аталады. Егер потенциалды қадамдар саны соңғы деп шамаласақ, онда алгоритмнен жан-жақты схема шығаруға болады:

PROCEDURE Try;

BEGIN кандидат таңдау инициациясы;

REPEAT кезекті кандидатты таңдау;

IF сәйкес келеді THEN BEGIN оның жазбасы ;

IF шешім толық емес THEN BEGIN Try;

IF сәтсіздік THEN жазбаны өшіру

END

END

UNTIL сәттілік OR кандидаттар енді жоқ

END; {Try}

Нақты программаларда схемадан алынатын басқа да нұсқалары кездеседі. Көбінесе, мысалы, рекурсияның тереңдігі көрсетілсе, деңгей үшін айқын өлшемдері бар салулар кездеседі. Бұл жұмысты аяқтаудың қарапайым шарттарына әкеледі. Сонымен бірге, егер әрбір қадамда зерттелетін жолдардың саны белгіленген болса (мейлі ол м-ге тең болсын), онда тағы бір шығарылған схеманы қолдануға болады (оған Try(1) операциясының көмегімен келу қажет).

1-кесте. Атпен үш мүмкін айналу.

23

10

15

4

25

23

4

9

14

25

16

5

24

9

14

10

15

24

1

8

11

22

1

18

3

5

22

3

18

13

6

17

20

13

8

16

11

20

7

2

21

12

7

2

19

21

6

17

12

19

1

16

7

26

11

14

34

25

12

15

6

27

17

2

33

8

13

10

32

35

24

21

28

5

23

18

3

30

9

20

36

31

22

19

4

29

PROCEDURE Try(i: INTEGER);

VAR k: INTEGER;

BEGIN k := 0;

REPEAT k := k+1; k-ші кандидатты таңдау;

IF сәйкес келеді THEN BEGIN

оның жазбасы;

IF i < n THEN BEGIN Try(i+1);

IF сәтсіздік THEN жазбаны өшіру

END

END

UNTIL сәттілік OR (k = m)

END; {Try}