Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Алгоритмы и структуры данных / методичка структуры данных_задания.docx
Скачиваний:
54
Добавлен:
12.05.2015
Размер:
381.84 Кб
Скачать

2.1. Алгоритми з поверненням

Такі алгоритми використовуються для задач, пов’язаних з “штучним інтелектом”. Вони характерні тим, що вирішують задачу не за фіксованими правилами, а методом спроб і помилок. Процес спроб і помилок поділяється на окремі підзадачі, які набільш природно описуються за допомогою рекурсії.

2.1.1. Шахова задача про хід коня

Дана дошка, розміром n x n, яка має n x n полів. Кінь, що може ходити за шаховими правилами, розміщується на полі з координатами x0, y0. Hеобхідно конем пройти по всім полям дошки, тобто виконати обхід дошки, якщо він існує, за (n*n ‑ 1) ходів, за умови, що на кожне поле кінь стає тільки один раз.

Очевидним є такий алгоритм: або виконати наступний хід, або він неможливий.

Procedure <Cпроба_наступного_ходу>;

Begin

Repeat

<вибір наступного з можливих ходів> {із списка чергових ходів}

If <хід можливий> Then

Begin

<записуємо хід>

If <дошка не заповнена> Then

Begin

<спроба наступного ходу>

If <невдача> Then

<видалення попереднього ходу>

End

End

Until <хід був вдалим> or <немає інших можливих ходів>

End

Виберемо подання для даних.

Дошку можна представити у вигляді матриці h розміром n x n.

Type

index=1..n;

Var

h : array [index,index] Of integer;

Для того, щоб мати історію “захвату” дошки, кожне захвачене поле будем позначати не булевим виразом, який тільки б підтверджував факт зайнятості, а цілим числом – порядковим номером ходу.

Для цього можна прийняти такі узгодження:

h[x,y]=0 – поле (x,y) не відвідувалось

h[x,y]=i – поле відвідувалося на i-тому ходу (1<= i <= n * n)

Параметри процедури повинні визначати початкові умови для наступного ходу, а також повідомляти про його вдалість чи невдалість. Початкові умови для наступного ходу визначаються заданням координат поля x, y, з якого треба робити хід, а також номером ходу i (для його фіксації). Для рішення останньої задачі необхідний булевий параметр-результат:

q=true – хід виконано;

q=false – хід не виконано.

Ще деякі узгодження:

якщо i<= n * n – дошка не заповнена;

якщо u та v – локальні змінні для координат ходу, то “хід можливий” за таких умов:

1<= u <=n та 1<= v <=n – тобто поле не за межами дошки

h[u,v]=0 – поле раніше не відвідувалось

фіксація ходу – h[u,v]=i;

стирання ходу – h[u,v]=0;

Звернемось до задачі:

Якщо задані початкові координати, то для наступного ходу є вісім різних можливостей вибору координат (u,v). Для того, щоб отримати з координат (x,y) координати (u,v), будемо додавати до них різниці координат, тобто відстань у клітинках поля від початкової позицїї коня до поточної, які будем зберігати у масивах a та b.

а= 2, 1, -1, -2, -2, -1, 1, 2

b= 1, 2, 2, 1, -1, -2, -2, -1

Рекурентна процедура перший раз викликається з параметрами x0,y0. Цьому полю присвоюється індекс 1.

{ “Хід коня” }

Program KnightSTore;

Const

n=5;

nsq=25;

Type

index=1..n;

Var

i,j : integer;

q : boolean;

s : set Of index;

a,b : array [1..8] Of integer;

h : array [index,index] Of integer;

Procedure Try(i:integer; x,y:index; Var q:boolean);

Var

k,ux,vy : integer;

q1 : boolean;

Begin

k:=0;

Repeat

k:=k+1;

q1:=false;

ux:=x+a[k];

vy:=y+b[k];

If (ux in s) and (vy in s) Then

If h[ux,vy]=0 Then

Begin

h[ux,vy]:=i;

If i<nsq Then

Begin

Try (i+1,ux,vy,q1);

If Notq1 Then

h[ux,vy]:=0;

End

Else

q1:=true;

End;

Until q1 or (k=8);

q:=q1;

End; {Try}

{—————————————————————————}

Begin

s:=[1,2,3,4,5];

a[1]:=2; b[1]:=1;

a[2]:=1; b[2]:=2;

a[3]:=-1; b[3]:=2;

a[4]:=-2; b[4]:=1;

a[5]:=-2; b[5]:=-1;

a[6]:=-1; b[6]:=-2;

a[7]:=1; b[7]:=-2;

a[8]:=2; b[8]:=-1;

{—————очистити дошку———————————}

For i:=1 To n Do

For j:=1 To n Do

h[i,j]:=0;

{—————починаємо з першої позиції————}

h[1,1]:=1;

Try(2,1,1,q);

Ifq Then

For i:=1 To n Do

Begin

For j:=1 To n Do

Write(h[i,j]:5);

Writeln;

End

Else

Writeln(‘Немає рішення’);

End.

Загальна схема алгоритма з поверненням назад має вигляд:

Procedure Try;

Begin

<ініціювати вибір можливих кроків>

Repeat

<вибрати наступний крок>

If <можливо> Then

Begin

<запам’ятати його>

If <рішення неповне> Then

Begin

<спробувати наступний крок>

If <невдача> Then

<стерти запис>

End;

End;

Until <хід зроблено> або <хід неможливий>;

End

Якщо кількість досліджуваних подальших путів розв’язку фіксовано, наприклад, m, тоді процедура може мати такий вигляд:

Procedure Try(i:integer);

Var

k:integer;

Begin

k:=0;

Repeat

k:=k+1;

If <можливий> Then

Begin

<записати>

If i<n Then

Begin

Try(i+1);

If <невдача> Then

<витерти запис>

End;

End;

Until <успіх> або (k=m);

End;