[英]How to find shortest path in X*Y grid
I have a grid N*M in Python.我在 Python 中有一个 N*M 网格。
where在哪里
"X" represents the border, “X”代表边界,
"1" represents current position, “1”代表当前位置,
"2" represents finish, and “2”代表完成,并且
"3" represents forbidden locations. “3”代表禁止位置。
The last thing is that (imagine you're a car) you can go only straight or right.最后一件事是(想象你是一辆车)你只能直行或右行。
Example 3x3 except borders:示例 3x3 除边框外:
[X,X,X,X,X]
[X,2,1,0,X]
[X,0,3,0,X]
[X,0,0,0,X]
[X,X,X,X,X]
Another example:另一个例子:
[X,X,X,X,X]
[X,2,0,0,X]
[X,3,3,1,X]
[X,X,X,X,X]
Or another:或其他:
[X,X,X,X,X,X,X]
[X,0,2,0,0,0,X]
[X,0,3,0,3,0,X]
[X,0,0,0,0,0,X]
[X,0,3,0,3,0,X]
[X,0,3,1,3,0,X]
[X,X,X,X,X,X,X]
Do you have any suggestion for concrete script that will find the fastest way?您对可以找到最快方法的具体脚本有什么建议吗?
And if there's not, print("No solution")?如果没有,打印(“无解”)?
Thank you very much!非常感谢!
To help you understand these situations:为了帮助您了解这些情况:
This was a fun one.这是一个有趣的。 A brute force approach calculates all possible paths through the system, and finally finds minimum path length of those ending in 2. Note that init just returns a valid matrix with which to work.蛮力方法计算通过系统的所有可能路径,并最终找到以 2 结尾的路径的最小路径长度。注意 init 只返回一个有效的矩阵。 If no solution is found for the matrix, None is returned by solve function.如果没有找到矩阵的解,solve 函数返回 None 。
BLOCK=3
FINAL=2
TERMINATE=None
INITIAL=1
PATH=0
def init(n,m):
# returns array with essential components, but not necessarily with solution
import numpy
import random
while True:
try:
a=numpy.zeros((n,m),dtype=int)
for i in range(n):
for j in range(m):
t=INITIAL
# initialize to anything but INITIAL
while t==INITIAL: t=numpy.random.randint(PATH,BLOCK)
a[i,j]=t
c=random.choice(list(zip(*(a==PATH).nonzero())))
a[c]=INITIAL
finals=list(zip(*(a==FINAL).nonzero()))
c=random.choice(finals)
for i in finals:
if i!=c: a[i]=BLOCK
break
except:
continue
return a
def possible_moves(a,pos):
n,m=a.shape
test_moves=[(0,1),(1,0),(-1,0),(0,-1)]
#print('from pos={}'.format(pos))
x,y=pos[0:2]
valid_moves=[]
for t in test_moves:
new=(t[0]+x,t[1]+y)
if t[0]+x>-1 and \
t[0]+x<n and \
t[1]+y>-1 and \
t[1]+y<m:
if a[new] not in [BLOCK]:
valid_moves.append((t[0]+x,t[1]+y))
return valid_moves
def allpaths(a,paths):
for path in paths:
if path[-1] in [TERMINATE,FINAL]: continue
pos=path[-1]
moves=possible_moves(a,pos)
if not moves:
path.append(TERMINATE) # if no moves left, path is terminated
continue
base=path.copy()
for im,move in enumerate(moves):
b=a.copy()
# set previous position to BLOCK so can't move into previous positions
b[pos]=BLOCK
if im==0:
if a[move]==FINAL: path.append(FINAL) # if position to move to is FINAL, indicate
else: path.append(move)
else:
if a[move]==FINAL: paths.append(base+[FINAL])
else: paths.append(base+[move])
paths=allpaths(b,paths)
return paths
def solve(a):
ipos=list(zip(*(a==INITIAL).nonzero()))
paths=[ipos]
paths=allpaths(a,paths)
M=a.shape[0]*a.shape[1]
minlen=M
for path in paths:
if path[-1] in [FINAL]:
minlen=min(minlen,len(path)-1)
if minlen==M: return None
else: return minlen
n,m=5,6
a=init(n,m)
print(n,m)
print(a)
minlen=solve(a)
print(minlen)
To capture "right," you could simply track previous position through to the possible_moves function, and ensure you are returning only "straight" and "right" directions ("backward" is already guarded against as it's encoded).要捕获“右”,您可以简单地通过 possible_moves 函数跟踪先前的位置,并确保您只返回“直”和“右”方向(“向后”在编码时已经受到保护)。
You can use this code, which based on Grap theory:您可以使用此代码,它基于 Grap 理论:
grid = [
['X','X','X','X','X','X','X'],
['X',2,0,0,0,0,'X'],
['X',0,3,0,3,0,'X'],
['X',0,0,0,0,0,'X'],
['X',0,3,0,3,0,'X'],
['X',0,3,1,3,0,'X'],
['X','X','X','X','X','X','X']
]
INF=1000000
def is_valid(grid:list):
ends = 0
starts = 0
for line in grid:
for el in line:
if el==2:
ends+=1
if el==1:
starts+=1
return False if ends!=1 or starts!=1 else True
def redef_grid(grid:list):
''' Deleting from grid all 'X' '''
g=grid.copy()
if 'X' in g[0]: del g[0]
if 'X' in g[-1]: del g[-1]
for line in g:
while 'X' in line:
line.remove('X')
return g
def uni_index(grid:list, pos:tuple):
return len(grid[0])*pos[0]+pos[1]
def real_index(grid:list, index:int):
row =index//len(grid[0])
col=index-row*len(grid[0])
return (row, col)
def get_neibs(grid:list, index:int):
def get_vertical(grid:list, index:int):
return [index+k for k in [len(grid[0]), -len(grid[0])] if index+k>=0 and index+k<uni_index(grid, (len(grid)-1, len(grid[0])-1))]
def get_horizontal(grid:list, index:int):
return [index+k for k in [1, -1] if index+k>=(index//len(grid[0]))*(len(grid[0])) and index+k<=uni_index(grid, (index//len(grid[0]), len(grid[0])-1))]
return get_vertical(grid, index)+get_horizontal(grid, index)
def get_matrix(grid:list):
last_el = uni_index(grid, (len(grid)-1, len(grid[0])-1))
elements=len(grid[0])*len(grid)
matrix=[[INF for _ in range(elements)] for _ in range(elements)]
for index in range(last_el):
neibs=get_neibs(grid, index)
neibs=[neib for neib in neibs if grid[real_index(grid, neib)[0]][real_index(grid, neib)[1]]!=3]
for neib in neibs:
matrix[index][neib]=1
return matrix
def get_start(grid:list):
for i in range(len(grid)):
try:
return (i, grid[i].index(1))
except ValueError:
pass
def get_end(grid:list):
for i in range(len(grid)):
try:
return (i, grid[i].index(2))
except ValueError:
pass
def Dijkstra(N, S, matrix):
valid = [True]*N
weight = [1000000]*N
weight[S] = 0
for i in range(N):
min_weight = 1000001
ID_min_weight = -1
for i in range(N):
if valid[i] and weight[i] < min_weight:
min_weight = weight[i]
ID_min_weight = i
for i in range(N):
if weight[ID_min_weight] + matrix[ID_min_weight][i] < weight[i]:
weight[i] = weight[ID_min_weight] + matrix[ID_min_weight][i]
valid[ID_min_weight] = False
return weight
grid=redef_grid(grid)
if is_valid(grid):
matrix=get_matrix(grid)
paths = Dijkstra(len(grid)*len(grid[0]), uni_index(grid, get_start(grid)), matrix)
shortest_path = paths[uni_index(grid, get_end(grid))]
if shortest_path==INF: shortest_path='No solution'
print(shortest_path)
else: print('Invalid grid')
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.