Хабр Курсы для всех
РЕКЛАМА
Практикум, Хекслет, SkyPro, авторские курсы — собрали всех и попросили скидки. Осталось выбрать!
Попадите в центральную область.
Попадите из входа, отмеченного стрелочкой к выходу, отмеченному стрелочкой, следуя правилу одной руки.при определённых ограничениях
Оно работает для любых лабиринтов при условии что мы начинаем и заканчиваем на краю.
А неплоский… лабиринт тоже довольно экзотичен для реального мира.

Было-бы интересно услышать, какие еще алгоритмы можно применить, для быстрого поиска пути в большом лабиринте?
Интересно стало узнать его прохождение и погуляв еще по сети, я так и не нашел, рабочей программной реализации, решения лабиринта.
'''
Created on 21.10.2013
@author: gridem
'''
import png
from copy import deepcopy
def toArray(filename):
_, _, lines, _ = png.Reader(filename=filename).asDirect()
return [[0 if pixel == 0 else 1 for pixel in line[::3]] for line in lines]
def fromArray(ar, filename):
def toPixel(v):
return {0: [0, 0, 0], 1: [0, 255, 0], 2: [255, 255, 255], 3: [255, 0, 0]}[v]
def flatten(l):
return [i for s in l for i in s]
im = [flatten([toPixel(v) for v in line]) for line in ar]
png.from_array(im, mode='RGB').save(filename)
def findPath(arSource):
ar = deepcopy(arSource)
beg = (0, 1)
end = (len(ar) - 2, len(ar[0]) - 1)
counter = [-1] # workaround
qu = []
def add(pnt):
qu.append((pnt, counter[0]))
def pop():
counter[0] += 1
return qu[counter[0]][0]
add(beg)
while True:
p = pop()
x, y = p
ar[x][y] = 2
if p == end:
break
def tryAdd((x, y), (dx, dy)):
if (ar[x+dx][y+dy] == 1):
add((x + dx, y + dy))
tryAdd(p, (0, 1))
tryAdd(p, (1, 0))
tryAdd(p, (0, -1))
tryAdd(p, (-1, 0))
cnt = counter[0]
while cnt >= 0:
(x, y), cnt = qu[cnt]
ar[x][y] = 3
return ar
ar1 = toArray('''input.png''')
ar2 = findPath(ar1)
fromArray(ar2, '''output.png''')

procedure setDeadblock;
var i,j:integer;
begin
for i:=1 to N-1 do
for j:=1 to N-1 do
setBlankAsDeadblockRec(i,j);
end;
Алгоритм такой:
Выполнять рекурсивную функцию по всем точкам дорог лабиринта:
1. Если мы стоим на дороге и вокруг нас 3 стены, помечаем место где мы стоим как тупик, в противном случае выходим из функции;
2. Переходим на место которое не является стенкой из пункта №1, и повторяем пункт №1;
for i:=1 to N-1 do на for i:=N-1 downto 1 do и посмотрите, что будет.if LABIRINT[x,y]=blank then //...Если мы стоим на дороге... begin if LABIRINT[x-1,y]<>BLANK then k:=k+1; if LABIRINT[x,y-1]<>BLANK then k:=k+1; if LABIRINT[x+1,y]<>BLANK then k:=k+1; if LABIRINT[x,y+1]<>BLANK then k:=k+1; if k=4 then LABIRINT[x,y]:=DEADBLOCK; if k=3 then//...и вокруг нас 3 стены... begin LABIRINT[x,y]:=DEADBLOCK; //...помечаем место где мы стоим как тупик.. if LABIRINT[x-1,y]=BLANK then setBlankAsDeadblockRec(x-1,y);//Переходим на место которое не является стенкой... if LABIRINT[x,y-1]=BLANK then setBlankAsDeadblockRec(x,y-1);//-//- if LABIRINT[x+1,y]=BLANK then setBlankAsDeadblockRec(x+1,y);//-//- if LABIRINT[x,y+1]=BLANK then setBlankAsDeadblockRec(x,y+1);//-//- end; end;//...в противном случае выходим из функции...
...
procedure setBlankAsDeadblockRec(x,y:integer);
var k:integer;
begin
k:=0;
if LABIRINT[x+1,y]<>BLANK then inc(k);
if LABIRINT[x,y+1]<>BLANK then inc(k);
if LABIRINT[x-1,y]<>BLANK then inc(k);
if LABIRINT[x,y-1]<>BLANK then inc(k);
if k=4 then LABIRINT[x,y]:=DEADBLOCK;
if k=3 then
begin
LABIRINT[x,y]:=DEADBLOCK;
if LABIRINT[x+1,y]=BLANK then setBlankAsDeadblockRec(x+1,y)
else if LABIRINT[x,y+1]=BLANK then setBlankAsDeadblockRec(x,y+1)
else if LABIRINT[x-1,y]=BLANK then setBlankAsDeadblockRec(x-1,y)
else if LABIRINT[x,y-1]=BLANK then setBlankAsDeadblockRec(x,y-1);
end;
end;
...
procedure setDeadblock;
var i,j:integer;
begin
for i:=1 to N-1 do
for j:=1 to N-1 do
if LABIRINT[i,j]=blank then setBlankAsDeadblockRec(i,j);
end;
...
...
procedure setBlankAsDeadblockRec(x,y:integer);
var k:integer;
begin
k:=0;
if LABIRINT[i,j]=blank then
begin
if LABIRINT[x+1,y]<>BLANK then inc(k);
if LABIRINT[x,y+1]<>BLANK then inc(k);
if LABIRINT[x-1,y]<>BLANK then inc(k);
if LABIRINT[x,y-1]<>BLANK then inc(k);
if k=4 then LABIRINT[x,y]:=DEADBLOCK;
if k=3 then
begin
LABIRINT[x,y]:=DEADBLOCK;
if LABIRINT[x+1,y]=BLANK then setBlankAsDeadblockRec(x+1,y)
else if LABIRINT[x,y+1]=BLANK then setBlankAsDeadblockRec(x,y+1)
else if LABIRINT[x-1,y]=BLANK then setBlankAsDeadblockRec(x-1,y)
else if LABIRINT[x,y-1]=BLANK then setBlankAsDeadblockRec(x,y-1);
end;
end;
end;
...
procedure setDeadblock;
var i,j:integer;
begin
for i:=1 to N-1 do
for j:=1 to N-1 do
setBlankAsDeadblockRec(i,j);
end;
...
Prepare data: 0:00:00.306268
Finish queue: 0:00:01.727277
Finish update image: 0:00:03.976633
Save image: 0:00:04.123483
from datetime import datetime
from PIL import Image, ImageDraw
class Queue:
def __init__(self, size):
self._queue = range(size)
self._size = size
self._left = 0
self._right = 0
def push(self, element):
self._queue[self._right] = element
self._right += 1
if self._right + 1 == self._left:
raise Exception('Small queue')
if self._right >= self._size:
self._right = 0
def pop(self):
element = self._queue[self._left]
self._left += 1
if self._left >= self._size:
self._left = 0
return element
def run(self, func_next_step):
while self._left != self._right:
elements = func_next_step(self.pop())
for element in elements:
self.push(element)
if __name__ == '__main__':
start = datetime.now()
image = Image.open('source.png')
draw = ImageDraw.Draw(image)
pix = image.load()
width = image.size[0]
height = image.size[1]
pixel = []
for y in xrange(height):
line = []
for x in xrange(width):
line.append(pix[x, y][0])
pixel.append(line)
move = (
(0, 1, ),
(1, 0, ),
(0, -1, ),
(-1, 0, ),
)
def recovery_path(item):
element = item
while element is not None:
x = element[0]
y = element[1]
if pixel[x][y] == 3:
break
pixel[x][y] = 3
element = element[2]
def next_step(item):
step = []
for vector in move:
x = item[0] + vector[0]
y = item[1] + vector[1]
if 0 <= x < width and 0 <= y < height:
if pixel[x][y] == 255:
pixel[x][y] = 1
step.append((x, y, item))
elif item[2] is not None:
recovery_path(item)
return step
pixel[0][1] = 3
queue = Queue(200)
queue.push((1, 0, None))
print "Prepare data : %s" % (datetime.now() - start)
queue.run(next_step)
print "Finish queue : %s" % (datetime.now() - start)
for y in xrange(height):
line = pixel[y]
for x in xrange(width):
type = line[x]
color = pix[x, y][0]
if type == 1:
draw.point((x, y), (128, 128, 128))
elif type == 2:
draw.point((x, y), (0, 255, 255))
elif type == 3:
draw.point((x, y), (0, 255, 0))
elif type == 0:
draw.point((x, y), (0, 0, 0))
else:
draw.point((x, y), (255, 0, 0))
if color == 0 and type != 0:
draw.point((x, y), (255, 0, 0))
print "Finish update image : %s" % (datetime.now() - start)
image.save('answer.png')
print "Save image : %s" % (datetime.now() - start)
procedure setPath;
var k,g:integer;
XX,YY:array [1..100000] of Integer;
begin
g:=0;
x:=1; y:=1; // начало пути
while ((x<>599) or (y<>599)) do // конец пути
begin
LABIRINT[x,y]:=DEADBLOCK;
k:=0;
if LABIRINT[x-1,y]=BLANK then k:=k+1;
if LABIRINT[x,y-1]=BLANK then k:=k+1;
if LABIRINT[x+1,y]=BLANK then k:=k+1;
if LABIRINT[x,y+1]=BLANK then k:=k+1;
if k>1 then
begin
g:=g+1;
XX[g]:=x;
YY[g]:=y;
end;
if k>=1 then
if LABIRINT[x-1,y]=BLANK then x:=x-1
else
if LABIRINT[x,y-1]=BLANK then y:=y-1
else
if LABIRINT[x+1,y]=BLANK then x:=x+1
else
if LABIRINT[x,y+1]=BLANK then y:=y+1;
if k=0 then
begin
if (x=XX[g]) and (y=YY[g]) then g:=g-1;
x:=XX[g];
y:=YY[g];
end;
end;
end;

if LABIRINT[x-1,y]=BLANK then x:=x-1
else if LABIRINT[x,y-1]=BLANK then y:=y-1
else if LABIRINT[x+1,y]=BLANK then x:=x+1
else if LABIRINT[x,y+1]=BLANK then y:=y+1;
if LABIRINT[x+1,y]=BLANK then x:=x+1
else if LABIRINT[x,y+1]=BLANK then y:=y+1
else if LABIRINT[x-1,y]=BLANK then x:=x-1
else if LABIRINT[x,y-1]=BLANK then y:=y-1;

procedure setBlankAsDeadblockRec(x,y:integer);
...
///смотрим ниже
...
...
if k=3 then
begin
LABIRINT[x,y]:=DEADBLOCK;
if LABIRINT[x+1,y]=BLANK then setBlankAsDeadblockRec(x+1,y);
if LABIRINT[x,y+1]=BLANK then setBlankAsDeadblockRec(x,y+1);
if LABIRINT[x-1,y]=BLANK then setBlankAsDeadblockRec(x-1,y);
if LABIRINT[x,y-1]=BLANK then setBlankAsDeadblockRec(x,y-1);
end;
...

и погуляв еще по сети, я так и не нашел, рабочей программной реализации, решения лабиринта
Алгоритм поиска путей в лабиринте