Скачиваний:
35
Добавлен:
01.05.2014
Размер:
1.1 Mб
Скачать

Лабиринт

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

Лабиринт имеет форму квадрата, который состоит из NN квадратных клеток, внутри которого вдоль сторон клеток могут быть расположены стены.

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

Одним ходом считается перемещение путешественника в соседнюю по горизонтали или по вертикали клетку. Путешественник может K раз проходить сквозь стену и не может выходить за пределы лабиринта.

Задание Составьте программу MAZE, которая вычислит минимальное количество ходов, за которое путешественник может добраться до источника с координатами (P, Q), начав путь в клетке с координатами (1, 1).

Входные данные Входной текстовый файл MAZE.DAT в первой строке содержит числа N, K, P, Q (2N200, 0K250, 1P,QN). Следующие N-1 строк содержат по N целых чисел — признаков наличия горизонтальных стен между клетками. Следующие N строк содержат N-1 целых чисел — признаков наличия вертикальных стен между клетками. 0 означает отсутствие стены, 1 – присутствие.

Пример входного файла

3 1 2 3 0 0 0

0 1 0

1 0

1 0

0 0

Выходные данные Единственная строка выходного текстового файла MAZE.SOL должна содержать найденное минимальное количество ходов, или число –1, если путь найти не удалось

Пример выходного файла 3

{$A-,B-,D-,E+,F-,G-,I+,L-,N+,O-,P-,Q+,R-,S-,T-,V+,X+,Y+}

{$M 16384,0,655360}

program Maze;

const

MaxN = 200;

type

tArr = array [1..MaxN, 1..MaxN] of byte;

pArr = ^tArr;

tPlainArr = array [0..MaxN*MaxN+100] of byte;

pPlainArr = ^tPlainArr;

var fr,fw:text;

n,k,x,y:integer;

H,V:pArr;

ma: tArr;

qx,qy:pPlainArr; {QueueX, QueueY - x and y coordinate of each maze's cell in

the queue, we stand in}

qb, qe: word; {Queue pointers to the beginning and the end of the data}

qm : word; {queue pointer to the last cell coordinates with current

prepared move - move delimiter}

qLength: word;

procedure PopQ(var x,y:byte);

begin

inc(qe);

if qe=qLength then qe:=0;

x:=qx^[qe]; y:=qy^[qe];

end;

procedure PushQ(x,y:byte);

begin

inc(qb);

if qb=qLength then qb:=0;

qx^[qb]:=x; qy^[qb]:=y;

end;

procedure Make;

var cx,cy,ck:byte;

cm:integer;

begin

qLength := word(n)*n+100; {maximal cells' count in the queue

+ 100 'na vsyakiy sluchai' :-) }

GetMem(qx, qLength);

GetMem(qy, qLength);

{queue initialization}

qb:=1; qe:=0;

qx^[1]:=1; qy^[1]:=1;

FillChar(ma, MaxN*MaxN, 255);

ma[1,1] := 0;

cm:=0; {move's counter}

qm:=1;

{while the queue is not empty or until we have find the result}

while (qb<>qe) do

begin

PopQ(cx, cy);

ck:=ma[cx,cy];

{generate ordinal moves first}

if (cx>1) and (H^[cx-1,cy]=0) and ( (ma[cx-1,cy]=255)or(ma[cx-1,cy]>ck) ) then

begin

PushQ(cx-1,cy);

ma[cx-1,cy]:=ck;

end;

if (cx<n) and (H^[cx,cy]=0) and ( (ma[cx+1,cy]=255)or(ma[cx+1,cy]>ck) ) then

begin

PushQ(cx+1,cy);

ma[cx+1,cy]:=ck;

end;

if (cy>1) and (V^[cx,cy-1]=0) and ( (ma[cx,cy-1]=255)or(ma[cx,cy-1]>ck) ) then

begin

PushQ(cx,cy-1);

ma[cx,cy-1]:=ck;

end;

if (cy<n) and (V^[cx,cy]=0) and ( (ma[cx,cy+1]=255)or(ma[cx,cy+1]>ck) ) then

begin

PushQ(cx,cy+1);

ma[cx,cy+1]:=ck;

end;

{generate magic moves last}

if (cx>1) and (H^[cx-1,cy]=1) and (ck<k) and

( (ma[cx-1,cy]=255)or(ma[cx-1,cy]>ck) ) then

begin

PushQ(cx-1,cy);

ma[cx-1,cy]:=ck+1;

end;

if (cx<n) and (H^[cx,cy]=1) and (ck<k) and

( (ma[cx+1,cy]=255)or(ma[cx+1,cy]>ck) ) then

begin

PushQ(cx+1,cy);

ma[cx+1,cy]:=ck+1;

end;

if (cy>1) and (V^[cx,cy-1]=1) and (ck<k) and

( (ma[cx,cy-1]=255)or(ma[cx,cy-1]>ck) ) then

begin

PushQ(cx,cy-1);

ma[cx,cy-1]:=ck+1;

end;

if (cy<n) and (V^[cx,cy]=1) and (ck<k) and

( (ma[cx,cy+1]=255)or(ma[cx,cy+1]>ck) ) then

begin

PushQ(cx,cy+1);

ma[cx,cy+1]:=ck+1;

end;

if qe=qm then

begin

inc(cm);

qm:=qb;

if ma[x,y]<>255 then break;

end;

end;

if ma[x,y]=255 then writeln(fw, '-1')

else writeln(fw, cm);

FreeMem(qy,qLength);

FreeMem(qx,qLength);

end;

var

i,j:integer;

begin

GetMem(H, MaxN*MaxN);

GetMem(V, MaxN*MaxN);

assign(fr, 'maze.dat');

reset(fr);

assign(fw, 'maze.sol');

rewrite(fw);

readln(fr, n, k, x, y);

for i:=1 to n-1 do

for j:=1 to n do

read(fr, H^[i,j]);

for i:=1 to n do

for j:=1 to n-1 do

read(fr, V^[i,j]);

if (x=1)and(y=1) then writeln(fw,'0')

else Make;

close(fw);

close(fr);

FreeMem(V, MaxN*MaxN);

FreeMem(H, MaxN*MaxN);

end.