Прямой ход волнового алгоритма.




заведём числовую таблицу V того же размера, что и L. Значением каждого элемента V(i,j) таблицы будет минимально возможное количество шагов, которые ведут из комнаты (i0,j0) в комнату (i,j) в лабиринте. Сначала заполним таблицу V числами -1.

Установим номер очередного шага h:=0.

Присвоим элементу V(i0,j0) значение h.

НЦПОКА V(ik,jk)= -1

Просматриваем клетки таблицы (i,j), в которых V(i,j)=h. По информации, содержащейся в L, заносим число h+1 во все клетки таблицы V, соответствующие комнатам смежным комнате (i,j), которые ещё содержат -1 (т.е ещё не проходились). После просмотра увеличиваем h на 1.

КЦ

Обратный ход волнового алгоритма

Установим текущее положение i:=ik, j:=jk.

Установим h:=(i,j).

НЦ пока h<>0

Используя информацию таблицы L, находим комнату, смежную комнате (i,j), в которой записано число h-1, и устанавливаем текущее положение, соответствующее найденной комнате. В зависимости от того, в какую сторону эта комната находится от предыдущей, выводим один из символов: "С", "Ю", "З" или "В".

Уменьшаем h на 1.

КЦ

 

Программная реализация:

type

ROOM=record

N,S,W,E:integer

end;

var

s:string; i0,j0,ik,jk,i,j,index,h:integer; l:array[1..50,1..50] of ROOM; v:array[1..50,1..50] of integer;

begin

ReadLn(s);

i0:=25; j0:=25; i:=i0; j:=j0;

for index:=1 to ord(s[0]) do

begin

if s[index]=’C’ then

begin

l[i,j].N:=1; l[i+1,j].S:=1; i:=i+1;

end;

if s[index]=’Ю’ then

begin

l[i,j].S:=1;

l[i-1,j].N:=1;

i:=i-1;

end;

if s[index]='З' then

begin

l[i,j].W:=1;

l[i,j-1].E:=1;

j:=j-1;

end;

if s[index]=’В’ then

begin

l[i,j].E:=1; l[i,j+1].W:=1; j:=j+1;

end;

end;

ik:=i; jk:=j;

for i:=1 to 50 do

for j:=1 to 50 do

v[i,j]:=-1;

h:=0;

v[i0,j0]:=h;

while v[ik,jk]=-1 do

begin

for i:=1 to 50 do

for j:=1 to 50 do

if v[i,j]=h then

begin

if (l[i,j].N=1) and (v[i+1,j]=-1) then

v[i+1,j]:=h+1;

if (l[i,j].S=1) and (v[i-1,j]=-1) then

v[i-1,j]:=h+1;

if (l[i,j].W=1) and (v[i,j-1]=-1) then

v[i,j-1]:=h+1;

if (l[i,j].E=1) and (v[i,j+1]=-1) then

v[i,j+1]:=h+1;

end;

h:=h+1;

end;

i:=ik; j:=jk; h:=v[i,j];

while v[i,j]<>0 do

begin

if (i+1<=50) and (v[i+1,j]=h-1) and (l[i,j].N=1)

then

begin

Write('С');

i:=i+1;

end

else

if (i-1>0) and (v[i-1,j]=h-1) and (l[i,j].S=1)

then

begin

Write(’Ю’);

i:=i-1;

end else if (j-1>0) and(v[i,j-1]=h-1) and (l[i,j].W=1)

then

begin Write('З'); j:=j-1;

end

else

if (j+1<=50) and(v[i,j+1]=h-1) and (l[i,j].E=1)

then

begin

Write('В');

j:=j+1;

end;

h:=h-1;

end;

Write(' ');

end.

 

ВАРИАНТ 2 (с использованием динамической памяти):

 

Procedure Wave (num_begin, num_end: integer);

{номера вершин начала и конца пути}

 

Var

k: integer; {номер «фронта волны»}

num: integer; {номер текущей вершины}

flag: boolean; {признак необходимости строить очередной фронт}

beg_qu, end_qu, elem_qu: list; {начало, конец элемента очереди}

Procedure Add (num: integer; var end_qu: list);

{добавление элемента к очереди}

Var

elem_qu: list;

begin

end_qu^.num:=num; {поместили элемент в конец очереди}

new(elem_qu); {выделили память под следующий элемент}

end_qu^.next:=elem_qu; {присоединили новый элемент}

end_qu:elem_qu

end;

Procedure Extract (var num: integer; var begin_qu: list);

{извлечь элемент из списка}

var

elem_qu: list;

begin

num:=beg_qu^.num; {считали первый элемент очереди}

elem_qu:=beg_qu; {запомнили ссылку на первый элемент для последующего уничтожения}

beg_qu:=beg_qu^.next; {переносим указатель начала очереди на второй элемент}

Dispose (elem_qu); {освобождаем память, уничтожив первый элемент}

end;

begin

new (elem_qu); {инициализация очереди и размещение в ней первого элемента}

beg_qu:=elem_qu; {очередь пока пуста}

end_qu:=elem_qu;

Graf [num begin].num:= 1; {начальный этап}

Add (num_begin, end_qu); {поместили начало пути в очередь}

Flag:=true; {нужно строить фронт}

While flag and (not goal) do {строим очередной фронт}

begin

Extract (num, beg_qu); {берём значение очередного элемента очереди}

k:= Graf [num].num; {число шагов до извлечённого элемента – 1}

{просмотреть соседей, поместить очередной фронт и добавить помеченные элементы в очередь}

ref:=Graf[num].next;

repeat

a:=ref^.num;

if a<>0 then begin

{обработка очередного соседа

if Graf [a].num=0

{пометить вершину следующим фронтом}

then begin

Graf[a].num:= k+1;

Add(a, end_qu)

End;

ref:=ref^.next

{переходим к следующему соседу}

end;

until a=0;

if Graf[num_end].num<>0

then goal:= true {дошли до цели}

else

if beg_qu = end_qu then flag false {очередь пуста}

end;

end.

 

 

7.4.4 АЛГОРИТМ ДЕЙКСТРЫ

Данный алгоритм находит наименьшую суммарную весовую стоимость от первой вершины до всех вершин графа (ориентированный граф с неотрицательными весами) за время О(N2).

Работа алгоритма:

- в процееса алгоритма некоторые города будут выделенными () в начале - только город 1, в конце – все);

- для каждого выделенного города I хранится наименьшая стоимость пути 1à I, при этом известно, что минимум достигается на пути, проходящем только через выделенные города;

- для каждого невыделенного города I хранится наименьшая стоимость путь 1à I, в котором в качестве промежуточных используются только выделенные города.

При выборе пути от вершины к вершине алгоритм действует «жадным» способом: выбирает выодящее ребро с наименьшим (наибольшим) весом.

Пример

 

 

На рисунке указаны стоимости ребер и порядок их обхода.

ПРОГРАММНАЯ РЕАЛИЗАЦИЯ:

program deikstra;

uses crt;

type sp=^elem; {Описание данных}

elem=record

nom,st:integer;

next:sp;

end;

const

n=10;

var a:array [1..n] of sp;

f,z,log:sp;

d,I,u,nach,konn:integer;

b:array [1..n] of integer;

c:array [1..n] of boolean;

{---------------------------------}

Procedure Add(var g:sp;i,den:integer);

Begin

new(f);

f^.nom:=i;

f^.st:=den;

f^.next:=g;

g:=f;

end;

{----------------------------------}

procedure Print(j:sp);

Begin

z:=j;

while z^.next<>nil do

Begin

write(' ',z^.nom,' ',z^.st,' ');

z:=z^.next;

end;

WRITELN;

end;

{-------------------------------------}

Procedure Lesen;

var i,x,y,ver:integer;

Begin

assign(input,'input.txt');

reset(input);

readln(d);

readln(nach,konn);

for i:=1 to d do

Begin

read(ver);

new(a[ver]);

a[ver]^.next:=nil;

repeat

read(x,y);

if (x<>0) and (y<>0) then add(a[ver],x,y);

until Eoln(input);

readln;

end;

close(input);

end;

{----------------------------------------}

{-------------------------------------}

Procedure Init;

{Удаляем в вершины до которых нельзя добраться и в массив цен

ставим очень большое число}

Begin

fillchar(c,sizeof(c),true);

for i:=1 to d do

Begin

if (a[i]^.nom=0) and (a[i]^.st=0) and (a[i]^.next=nil) then

c[i]:=false;

b[i]:=32760;

end;

b[nach]:=0;

end;

{-------------------------------------}

function Proverka:boolean;

begin

Proverka:=false;

for i:=1 to d do

Begin

if c[i]=true then Begin Proverka:=true; exit; end;

end;

end;

{----------------------------------------}

function Min:integer;

var i,m,nomer:integer;

Begin

m:=32767;

nomer:=-1;

for i:=1 to d do

Begin

if (m>b[i]) and (c[i]<>false) then Begin m:=b[i];nomer:=i;;end;

end;

Min:=nomer;

end;

{---------------------------------------}

function Srav(sn,ss,pv:integer):boolean;

Begin

Srav:=(b[pv]+ss)<b[sn];

end;

{--------------------------------------}

Begin

clrscr;

Lesen;

Init;

while Proverka do

Begin

U:=Min;

c[u]:=false;

while (a[u]^.next<>nil)do

Begin

if srav(a[u]^.nom,a[u]^.st,u) then

b[a[u]^.nom]:=b[u]+a[u]^.st;

log:=a[u];

a[u]:=a[u]^.next;

dispose(log);

end;

end;

writeln(b[konn]);

end.

 

 

ЗАДАЧИ ДЛЯ САМОСТОЯТЕЛЬНОЙ РЕАЛИЗАЦИИ УЧАЩИМИСЯ:

 

Задача 1. ПУТЬ.

Найти кратчайшее расстояние между двумя заданнымивершинами в графе. Найти все возможные пути между этими двумя вершинами.

 

Задача 2.

Лабиринт задается матрицей смежности N*N, где C(i,j)=1, если узел i связан узлом j посредством дороги. Часть узлов назначается входами, часть - выходами. Входы и выходы задаются последовательностями узлов X(1),..,X(p) и Y(1),..,Y(k) соответственно.

Найти максимальное число людей, которых можно провести от входов до выходов таким образом, чтобы:

а) их пути не пересекались по дорогам, но могли пересекаться по узлам;

б) их пути не пересекались по узлам;

 

Задача 3.

N шестеpенок пpонумеpованы от 1 до N (N<= 10). Заданы M (0<= <=M<=45) соединений паp шестеpенoк в виде (i,j), 1<=i<j<=N (шестеpня с номеpом i находится в зацеплении с шестеpней j). Можно ли повеpнуть шестеpню с номеpом 1?

Если да, то найти количество шестеpен, пpишедших в движение.

Если нет, то тpебуется убpать минимальное число шестеpен так, чтобы в оставшейся системе пpи вpащении шестеpни 1 во вpащение пpишло бы максимальное число шестеpен. Указать номеpа убpанных шестеpен (если такой набоp не один, то любой из них) и количество шестеpен, пpишедших в движение.

 

 

Задача 4.

Имеется N прямоугольных конвертов и N прямоугольных открыток различных размеров. Можно ли разложить все открытки по конвертам, чтобы в каждом конверте было по одной открытке. Замечание. Открытки нельзя складывать, сгибать и помещать в конверт под углом. Например, открытка с размерами сторон 5:1 помещается в конверты с размерами 5:1, 6:3, 4.3:4.3, но не входит в конверты с размерами 4:1, 10:0.5, 4.2:4.2.

 

Задача 5.

Составить программу для нахождения произвольного разбиения 20 студентов на 2 команды, численность которых отличается не более чем в 2 раза, если известно, что в любой команде должны быть студенты, обязательно знакомые друг с другом. Круг знакомств задается матрицей (20,20) с элементами

A(ij)={1,если i знаком с j}

{0,иначе}.

 

Задача 6.

Имеется N человек и прямоугольная таблица А[1:N,1:N];элемент A[i,j] равен 1, если человек i знаком с человеком j, А[i,j]=А[j,i]. Можно ли разбить людей на 2 группы, чтобы в каждой группе были только незнакомые люди?

 

 

Задача 7.

Пусть группа состоит из N человек. В ней каждый имеет (N/2) друзей и не больше K врагов. У одного из них есть книга, которую все хотели бы прочитать и потом обсудить с некоторыми из остальных.

Написать программу, которая:

- Находит способ передачи книги таким образом, чтобы она побывала у каждого в точности один раз, переходя только от друга к другу и наконец возвратилась к своему владельцу.

- Разбивает людей на S групп, где будет обсуждаться книга, таким образом, чтобы вместе с каждым человеком в ту же самую группу вошло не более P его врагов.

Примечание: предполагается, что S*P>=K.

 

Задача 9.

В заданном графе необходимо определить, существует ли цикл, проходящий по каждому ребру графа ровно один раз.

 

 

Задача 10.

Имеется N городов. Для каждой пары городов (I,J) можно построить дорогу, соединяющую эти два города и не заходящие в другие города. Стоимость такой дороги A(I,J). Вне городов дороги не пересекаются.

Написать алгоритм для нахождения самой дешевой системы дорог, позволяющей попасть из любого города в любой другой. Результаты задавать таблицей B[1:N,1:N], где B[I,J]=1 тогда и только тогда, когда дорогу, соединяющую города I и J, следует строить.

 

Задача 11.

В картинной галерее каждый сторож работает в течение некоторого непрерывного отрезка времени. Расписанием стражи называется множество пар [Т1(i), Т2(i)] - моментов начала и конца дежурства i-го сторожа из интервала [0,EndTime].

Для заданного расписания стражи требуется:

(а) проверить, в любой ли момент в галерее находится не менее двух сторожей.

Если условие (а) не выполнено, то:

(б) перечислить все интервалы времени с недостаточной охраной (менее 2 сторожей).

(в) добавить наименьшее число сторожей с заданной, одинаковой для всех длительностью дежурства, чтобы получить правильное расписание (т.е. удовлетворяющее условию (а)).

(г) проверить, можно ли обойтись без добавления новых сторожей, если разрешается сдвигать времена дежурства каждого из сторожей с сохранением длительности дежурства.

(д) Если это возможно, то составить расписание с наименьшим числом сдвигов.

 

Задача 12.

Вводится N - количество домов и К - количество дорог. Дома пронумерованы от 1 до N. Каждая дорога определяется тройкой чисел - двумя номерами домов - концов дороги и длиной дороги. В каждом доме живет по одному человеку. Найти точку - место встречи всех людей, от которой суммарное расстояние до всех домов будет минимальным.

Если точка лежит на доpоге, то указать номера домов – концов этой доpоги и расстояние от первого из этих домов. Если точка совпадает с домом, то указать номер этого дома.

Примечание: длины дорог - положительные целые числа.

 

Задача 13.

N колец сцеплены между собой (задана матрица A(n*n), A(i,j)=1в случае, если кольца i и j сцеплены друг с другом и A(i,j)=0 иначе). Удалить минимальное количество колец так, чтобы получилась цепочка.

 

Задача 14.

Янка положил на стол N выпуклых K-гранников и N различных типов наклеек по K штук каждая. Ночью кто-то наклеил наклейки на грани, по одной на грань. Помогите Янке расставить многогранники так, чтобы наклейка

каждого типа была видна pовно K-1 раз.

 

Задача 15.

Имеется N точек и M проводков. Проводком можно соединить некоторую пару различных точек, причем пара может быть соединена не более чем одним проводком. Все проводки должны быть использованы.

Пусть Di - количество проводков, которые будут соединены с точкой с номером i, i=1,..., N.

Необходимо соединить N точек с помощью M проводков таким образом, чтобы сумма S=D1*D1 + D2*D2 +... + Dn*Dn была максимальной.

Вывести величины Di в неубывающем порядке и. по требованию (priznak=1), список соединений.

 

ВВОД:

<Введите N:> N (N<=100)

<Введите M:> M (M<=1000)

<PRIZNAK=> PRIZNAK

ВЫВОД:

<Результирующая конфигурация:> Di в неубывающем порядке.

<Сумма S> S

<Список соединений>

<Точку 1 соединить с> список точек

.....

<Точку N соединить с> список точек

Задача 16.

Задано N городов c номерами от 1 до N и сеть из M дорог с односторонним движением между ними. Каждая дорога задается тройкой (i, j, k), где i - номер города, в котором дорога начинается, j - номер города, в котором дорога заканчивается, а k - ее длина (число k - натуральное). Дороги друг с другом могут пересекаться только в концевых городах.

Все пути между двумя указанными городами A и B можно упорядочить в список по неубыванию их длин (если есть несколько путей одинаковой длины, то выбираем один из них). Необходимо найти один из путей, который может быть вторым в списке.

Вывести его длину L и города, через которые он проходит.

 

ВВОД:

<Количество городов N:> N

<Количество дорог M:> M

<Начало, конец и длина дороги 1:> i1, j1, k1

......

<Начало, конец и длина дороги M:> iM, jM, kM

<Города A и B, между которыми надо найти путь:> A, B

ВЫВОД:

<Пути нет>

или

<Путь проходит по городам> A, i1, i2,..., B

<Длина пути> L

 

Задача 17. Ларсона

Пусть G - конечный неориентированный связный граф. Предположим, что он представляет собой систему тоннелей, в которых может прятаться беглец. Группа из S полицейских, двигаясь по туннелям, стремится схватить этого беглеца, который может двигаться с любой скоростью, стремясь избежать поимки. Требуется определить минимальное количество полицейских S, гарантирующих поимку беглеца.

 

[s1]аль



Поделиться:




Поиск по сайту

©2015-2024 poisk-ru.ru
Все права принадлежать их авторам. Данный сайт не претендует на авторства, а предоставляет бесплатное использование.
Дата создания страницы: 2018-01-08 Нарушение авторских прав и Нарушение персональных данных


Поиск по сайту: