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

Лабораторна робота № 13 лабіринт

Завдання: розробити алгоритми і написати програми, проходження через лабіринт. Розглянути дві версії: евристику лівої руки і метод ковзаючого вікна.

Версія 1 . Евристика лівою руки. Щоб пройти лабіринт до виходу з нього або повернутися в точку входу, коли проходу з даної початкової точки немає (тобто не заблукати!), необхідно рухатися весь час торкаючись стіни лівою рукою (продумайте це!)

Представлення даних:

вхідні дані: бінарна матриця L (M,n)‚ де:

M - кількість рядків (висота лабіринту)

N - кількість стовпців (ширина лабіринту)

s - індекс рядка

до - індекс стовпця

L (s, до) = 1 - прохід

L (s, до) = 0 - стіна

s (рядок)

­ V (вхід)

0 1 0 0 0 0

0 1 1 1 1 0

0 0 1 0 0 0 (можливий вихід)

0 0 1 1 1 1  W1

(можливий вихід) W3  1 1 1 0 0 0

0 0 1 0 0 0

 k (колонка)

W2 (можливий вихід)

V, наприклад, V = L(1,2) - точка входу

Н - напрям, з якого увійшли до лабіринту (далі - в поточну крапку)

Н ::= 1, якщо прибув зверху

Н ::= 2, якщо прибув справа

Н ::= 3, якщо прибув знизу і

Н ::= 4, якщо прибув зліва.

вихідні дані:

маршрут через лабіринт у вигляді послідовності координат

(X(i) - горизонтальна, Y(i) - вертикальна)

прохідних точок лабіринту аж до досягнення граничної крапки.

Граничною крапкою (вона ж точка виходу з лабіринту) є крапка, для якої

s = 1 або s = m або до = 1 або до = n (продумайте це!)

тобто умовою завершення роботи є досягнення граничної крапки:

Ідея рішення і її формалізація:

евристика лівої руки - рухатися в лабіринті весь час тримаючись стіни лівою рукою

1) гарантує відшукання виходу, якщо він є, або повернення в початкову точку, якщо виходу немає

2) не гарантує знаходження глобального екстремуму, тобто знайдений маршрут не обов'язково є найкоротшим (наприклад, з V(1,2) може бути знайдений тільки вихід W1 за 12 кроків 1-2-3-4-5-4-3-6-7-8-9-10, а найближчий вихід W2, доступний за 7 кроків 1-2-3-6-7-13-14, знайти неможливо:

 V

0 1 0 0 0 0

0 2 3 4 5 0

0 0 6 0 0 0

0 0 7 8 9 10  W1

W3  11 12 13 0 0 0

0 0 14 0 0 0

 W2

3) дуже просто формалізується за допомогою прапора Н = <напрям прибуття>. Дійсно, абстрактний оператор <рухатися весь час тримаючись стіни лівою рукою>

означає одне і лише одне: з кожної чергової i-й точки лабіринту необхідно намагатися пройти спочатку вліво, потім - прямо, управо або назад і обов'язково у вказаному порядку, а для цього і потрібний прапор напряму прибуття.

Наприклад, якщо ми прийшли в i-ю крапку зверху, то евристика лівої руки припускає наступну схему спроб відшукання i+1 точки шляху через лабіринт

s

Н = 3 повернення   напрям прибуття Н = 1

s = s - 1, k = k

1-а спроба

3-а спроба  i  H = 4

H = 2 s = s, k = k + 1

s = s, k = k - 1 

­

2-а спроба Н=1­, s = s + 1, k = k k

в результаті евристика може бути реалізована, наприклад, таким чином

(i) ввести напрям і координати точки входу input H, s і до;

(ii) запам'ятати першу точку шляху через лабіринт i = 1, X(i)= до, Y(i)= s;

(iii) цикл пошуку

do

case H

1 : <прибувЗверху>

2 : <прибувСправа>

3 : <прибувЗнизу>

4 : <прибувЗлiва>

fi; inc(i)

until s=1 or s=m or k=1 or k=n od;

(iv) виведення маршруту:

print <маршрут через лабіринт >; for j=1 to i do writeln (X(j), Y(j)) od;

Залежно від напряму прибуття перемикач H викликає один з операторів: <прибувЗверху >, < прибувСправа>, <прибувЗнизу> або < прибувЗлiва >.

Всі ці оператори виконують одне і те ж: перевіряють за годинниковою стрілкою сусідні клітки і залежно від того, яка з них першою

виявиться прохідною, викликає відповідного оператора <йтивправо>, <йтивниз>, <йтивліво> або <йтиверх>

do <прибув Зверху>:

if L(s, k + 1) = 1 then <йтиВправо>; break fi

if L(s + 1, k) = 1 then <йтиВниз>; break fi

if L(s, k - 1) = 1 then <йтиВліво>; break fi

<йтиВерх> 'назад

Od

do <прибувСправа>:

if L(s + 1, k) = 1 then <йтиВниз>; break fi

if L(s, k - 1) = 1 then <йтиВліво>; break fi

if L(s - 1, k) = 1 then <йтиВерх>; break fi

<йтиВправо> 'назад

Od

do <прибувЗнизу>:

if L(s, k - 1) = 1 then <йтиВліво>; break fi

if L(s - 1, k) = 1 then <йтиВерх>; break fi

if L(s, k + 1) = 1 then <йтиВправо>; break fi

<йтиВниз> 'назад

od

do <прибувЗліва>:

if L(s - 1, k) = 1 then <йтиВерх>; break fi

if L(s, k + 1) = 1 then <йтиВправо>; break fi

if L(s + 1, k) = 1 then <йтиВниз>; break fi

<йтиВліво> 'назад

od

оператори< йтиВправо>, < йтиВниз >, < йтиВліво > и < йтиВерх >, використовувані в операторах <прибувЗверху>, <прибувСправа>, <прибувЗнизу> і <прибувЗліва>, тривіально реалізуються через:

1) інкремент/декремент належної координати

2) інкремент індексу нової точки шляху через лабіринт і

3) відповідну модифікацію прапора напряму

другими словами:

do < йтиВправо >: H = 4; inc(i); inc(k); X(i) = k, Y(i) = s od

do < йтиВниз >: H = 1; inc(i); inc(s); X(i) = k, Y(i) = s od

do < йтиВліво >: H = 2; inc(i); dec(k); X(i) = k, Y(i) = s od

do < йтиВерх >: H = 3; inc(i); dec(s); X(i) = k, Y(i) = s od

Розробка решти модулів тривіальна і залишаємо її як домашнє завдання для лабораторної роботи.