- •Введення
- •Список лабораторних робіт
- •Оформлення звіту по лабораторній роботі
- •Правила написання програм
- •Правила виконання схем алгоритмів
- •Лабораторна робота № 1 лінійний обчислювальний процес
- •Лабораторна робота № 2 обчислювальний процес, що розгалужується
- •Лабораторна робота № 3 циклічний процес
- •Лабораторна робота № 4 типи даних, визначувані програмістом
- •Лабораторна робота № 5 робота з одновимірними і двовимірними масивами
- •Лабораторна робота № 6 сортування одно і двовимірних масивів.
- •Лабораторна робота № 7 функції і процедур, визначувані програмістом
- •Лабораторна робота № 8 модулі і динамічно зв'язувані бібліотеки.
- •Лабораторна робота № 9 множини і операції над ними
- •Лабораторна робота № 10 комбіновані типи (записи )
- •Лабораторна робота № 11 файли і робота з ними
- •Лабораторна робота № 12 статистичнi I динамiчнi структури даних
- •Лабораторна робота № 13 лабіринт
- •Лабораторна робота № 14 евристики.
- •Лабораторна робота № 15 класи
Лабораторна робота № 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
Розробка решти модулів тривіальна і залишаємо її як домашнє завдання для лабораторної роботи.