Студопедия

КАТЕГОРИИ:


Архитектура-(3434)Астрономия-(809)Биология-(7483)Биотехнологии-(1457)Военное дело-(14632)Высокие технологии-(1363)География-(913)Геология-(1438)Государство-(451)Демография-(1065)Дом-(47672)Журналистика и СМИ-(912)Изобретательство-(14524)Иностранные языки-(4268)Информатика-(17799)Искусство-(1338)История-(13644)Компьютеры-(11121)Косметика-(55)Кулинария-(373)Культура-(8427)Лингвистика-(374)Литература-(1642)Маркетинг-(23702)Математика-(16968)Машиностроение-(1700)Медицина-(12668)Менеджмент-(24684)Механика-(15423)Науковедение-(506)Образование-(11852)Охрана труда-(3308)Педагогика-(5571)Полиграфия-(1312)Политика-(7869)Право-(5454)Приборостроение-(1369)Программирование-(2801)Производство-(97182)Промышленность-(8706)Психология-(18388)Религия-(3217)Связь-(10668)Сельское хозяйство-(299)Социология-(6455)Спорт-(42831)Строительство-(4793)Торговля-(5050)Транспорт-(2929)Туризм-(1568)Физика-(3942)Философия-(17015)Финансы-(26596)Химия-(22929)Экология-(12095)Экономика-(9961)Электроника-(8441)Электротехника-(4623)Энергетика-(12629)Юриспруденция-(1492)Ядерная техника-(1748)

Вывод 1 Вывод 2 Вывод 3




Ввод 1 Ввод 2 Ввод 3

Примеры

Поиск в ширину. Волновой алгоритм

 

Поиск в ширину также встречался в задаче поиска путей на графе. Есть множество других задач, для решения которых используется этот же подход. Если при поиске в глубину последовательно достраивается единственное частичное решение, то при поиске в ширину происходит переход от одного частичного решения к другому. Поиск решения производится широким фронтом. Типичным примером поиска в ширину является алгоритм Дейкстры поиска кратчайшего пути на графе.

Рассмотрим схему поиска в ширину на следующем примере.

Игра Lines. В таблице из N строк и N столбцов некоторые клетки заняты шариками, другие свободны. Выбран шарик, который нужно переместить, и место, куда его нужно переместить. Выбранный шарик за один шаг перемещается в соседнюю по горизонтали или вертикали свободную клетку. Требуется выяснить, возможно ли переместить шарик из начальной клетки в заданную, и, если возможно, то найти путь из наименьшего количества шагов.

Ввод из файла INPUT.TXT. В первой строке находится число N, в следующих N строках - по N символов. Символом точки обозначена свободная клетка, латинской заглавной O - шарик, @ - исходное положение шарика, который должен двигаться, латинской заглавной X - конечное положение шарика.

Вывод в файл OUTUT.TXT. В первой строке выводится Y, если движение возможно, или N, если нет. Если движение возможно, далее следует N строк по N символов - как и на вводе, но буква X, а также все точки по пути заменяются плюсами.

Ограничения: 2 ≤ N ≤ 40, время 1 с.

5 5 5

....X..X.....X.

.OOOO..........

..... OOOOO O.OOO

OOOO...........

@......@......@

Y N Y

+++++..++.

+OOOO.++..

+++++ O+OOO

OOOO+.++++

@++++....@

 

Для решения задачи используется так называемый волновой алгоритм. В целях удобства организуем барьер, объявив двумерный массив от 0 до N +1 по каждому измерению. Во все барьерные клетки занесем признаки занятости в виде символов ‘O’. Это избавит нас от необходимости проверять каждый раз, находимся ли мы на краю поля.

В начальную клетку поместим числовую метку 0. Далее во все соседние с ней пустые клетки занесем метку 1. Во все соседние клетки с меткой 1, помеченные символом ‘.’ как свободные, поместим метку 2 и т. д. Будем считать на каждом шаге количество вновь занесенных меток.

В конце концов, возможна одна из двух ситуаций:

· на очередном шаге помечена конечная клетка;

· новых меток не появилось.

В первом случае значение метки K равно длине кратчайшего пути из начальной клетки в конечную. Сам путь восстанавливается в обратном направлении. Для конечной клетки находится одна из соседних к ней, имеющая метку K -1. Потом от нее находится следующая клетка с меткой K -2 и так до тех пор, пока не придем в начальную клетку.

Второй случай говорит об отсутствии решения.

Проще всего на каждом шаге находить все клетки с определенным значением метки полным перебором. Такой подход не годится для больших размерностей. В программе Lines, приведенной ниже, клетки, получающие очередные метки, записываются в кольцевую очередь. Выбор клеток из начала очереди обеспечивает просмотр по возрастанию меток.

 

Program Lines;

Const

Max=150;

Raz=10*Max; {максимальный размер очереди}

Type

Coord=record

X,Y:byte; {координаты}

end;

Me=record

X,Y: byte; {координаты}

Metka: integer; {числовая метка}

end;

Var

i,j,k,Met,p,q: integer;

N,M: integer; {размер участка}

C: array[1..Max,1..Max] of char;

From: array[0..Max+1,0..Max+1] of char;

{откуда получена метка: U-сверху, D-снизу, L-слева, R-справа}

{используется также как рабочая карта поля с барьером из 'O'}

Fin,Fout: text;

Och: array[1..Raz] of Me;

{кольцевая очередь для поиска в ширину}

BegO,EndO,Count: integer; {для кольцевой очереди}

Nach,Kon: Coord; {начальная и целевая клетки для поиска в ширину}

b: boolean; {признак нахождения решения}

Procedure Zanes(u,v: byte; Var Res: boolean);

{ занесение в конец кольцевой очереди }

{ (u,v)-текущая клетка, Res=true-дошли до конца }

Begin

if (u=Kon.X) and (v=Kon.Y) then

Res:=true {достижение цели}

else

begin

Res:=false;

EndO:=(EndO mod Raz)+1; {кольцевая очередь}

Och[EndO].X:=u;

Och[EndO].Y:=v;

Och[EndO].Metka:=Met+1; {текущая числовая метка}

Count:=Count+1;

end;

End;

Begin

Assign(Fin,'input.txt');

Reset(Fin);

ReadLn(Fin,N);

For i:=0 to N+1 do

For j:=0 to N+1 do

From[i,j]:='O'; {барьер}

For i:=1 to N do

begin

For j:=1 to N do

begin

Read(Fin,C[i,j]);

From[i,j]:=C[i,j]; { сначала копия C }

if From[i,j]='@' then {начало}

begin

Nach.X:=i;

Nach.Y:=j;

From[i,j]:='O'; {запрет, чтобы не возвращаться}

end;

if From[i,j]='X' then {конец}

begin

Kon.X:=i;

Kon.Y:=j;

From[i,j]:='.';

end;

end;

ReadLn(Fin); {перевод строки}

end;

Close(Fin);

BegO:=1; {кольцевая очередь для расстановки меток в ширину}

EndO:=1;

Count:=1; {длина очереди}

Och[BegO].Metka:=0;

Och[1].X:=Nach.X; Och[1].Y:=Nach.Y; {начальная точка}

b:=false;

While Count>0 do

begin

p:=Och[BegO].X;

q:=Och[BegO].Y;

Met:=Och[BegO].Metka;

Och[BegO].X:=0; {для наглядности отладки}

Och[BegO].Y:=0;

BegO:=(BegO mod Raz)+1;

Count:=Count-1; {выбор клетки из начала очереди}

{далее занесение соседних клеток в конец очереди}

if From[p,q+1]='.' then {можно идти направо}

begin

Zanes(p,q+1,b); {занесение в очередь}

From[p,q+1]:='L'; {пришли слева}

if b then Break; {достигли заданной клетки}

end;

if From[p+1,q]='.' then {можно идти вниз}

begin

Zanes(p+1,q,b); {занесение в очередь}

From[p+1,q]:='U'; {пришли сверху}

if b then Break; {достигли заданной клетки}

end;

if From[p,q-1]='.' then {можно идти налево}

begin

Zanes(p,q-1,b);

From[p,q-1]:='R'; {пришли справа}

if b then Break; {достигли заданной клетки}

end;

if From[p-1,q]='.' then {можно идти вверх}

begin

Zanes(p-1,q,b);

From[p-1,q]:='D'; {пришли снизу}

if b then Break; {достигли заданной клетки}

end;

end;

{здесь оказываемся либо при нахождении решения, либо

по исчерпанию очереди, когда больше помечать нечего}

Assign(Fout,'output.txt');

Rewrite(Fout);

if b then {найдено решение}

begin

WriteLn(Fout,'Y');

p:=Kon.X; q:=Kon.Y; {восстановление от конца}

For i:=1 to Met+1 do {клетку '@' не меняем}

begin

C[p,q]:='+';

Case From[p,q] of

'U': p:=p-1;

'D': p:=p+1;

'L': q:=q-1;

'R': q:=q+1;

end;

end;

For i:=1 to N do

begin

For j:=1 to N do Write(Fout,C[i,j]);

WriteLn(Fout); {перевод строки}

end;

end

else WriteLn(Fout,'N');

Close(Fout);

End.




Поделиться с друзьями:


Дата добавления: 2014-01-11; Просмотров: 942; Нарушение авторских прав?; Мы поможем в написании вашей работы!


Нам важно ваше мнение! Был ли полезен опубликованный материал? Да | Нет



studopedia.su - Студопедия (2013 - 2024) год. Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав! Последнее добавление




Генерация страницы за: 0.009 сек.