小明置身于一个迷宫,请你帮小明找出从起点到终点的最短路程。
小明只能向上下左右四个方向移动。
输入包含多组测试数据。输入的第一行是一个整数T,表示有T组测试数据。
每组输入的第一行是两个整数N和M(1<=N,M<=100)。
接下来N行,每行输入M个字符,每个字符表示迷宫中的一个小方格。
字符的含义如下:
‘S’:起点
‘E’:终点
‘-’:空地,可以通过
‘#’:障碍,无法通过
输入数据保证有且仅有一个起点和终点。
输入:
1
5 5
S-###
-----
##---
E#---
---##
输出:
9
1.广度优先算法
from collections import deque
T = int(input())
dirs = [
lambda x,y:(x+1,y), #向右
lambda x,y:(x,y+1), #向下
lambda x,y:(x-1,y), #向左
lambda x,y:(x,y-1) #向上
]
def output(path):
now = path[-1] #最后一个点的坐标,即终点
lt = [] #从起点到终点经过的路径
while now[2] != -1:
lt.append((now[0],now[1]))
now = path[now[2]]
lt.append((now[0],now[1])) #存入起点坐标
#lt.reverse()
return len(lt)-1
def find(l,x1,y1,x2,y2):
que = deque() #新建队列
que.append((x1,y1,-1))
path = [] #走过点的坐标
while len(que) != 0:
now = que.popleft() #注意要左出队
path.append(now)
if now[0] == x2 and now[1] == y2:
return output(path)
for dir in dirs:
next = dir(now[0],now[1])
if next[0] < 0 or next[0] >= n or next[1] < 0 or next[1] >= m:
continue
if l[next[0]][next[1]] in ['-','E']: #可走
#l[next[0]][next[1]] = '+'
#len(path)-1是上一个点在path中所在位置的下标
que.append((next[0],next[1],len(path)-1))
else:
return -1
for li in range(T):
n,m = map(int,input().split())
lt = []
#lt.append(list('#'*(m+2)))
for i in range(n):
l = list(input())
if 'S' in l: #起点坐标
y1 = l.index('S'); x1 = i
if 'E' in l: #终点坐标
y2 = l.index('E'); x2 = i
lt.append(l)
#lt.append(list('#'*(m+2)))
print(find(lt,x1,y1,x2,y2))
2.模拟C结构体数组
class stu:
x = 0
y = 0
step = 0
c = [[1, 0],[0, 1],[-1, 0],[0, -1]]
n = int(input())
while(n):
n -= 1
N, M = map(int,input().split(" "))
son = []
a = []
b = [0] * N * M
stus = []
for i in range(0, N):
son = input()
for j in range(0, M):
if son[j] == 'S':
x0 = i
y0 = j
if son[j] == 'E':
x1 = i
y1 = j
stus.append(stu())
a.append(son)
son = []
for i in range(0, N):
b[i] = [0] * M
h = t1 = v = 0
stus[t1].x = x0
stus[t1].y = y0
stus[t1].step = 0
t1 += 1
while(h < t1):
for i in range(0, 4):
newX = stus[h].x + c[i][0]
newY = stus[h].y + c[i][1]
if(newX<0 or newX>=N or newY<0 or newY>=M):
continue
if(b[newX][newY] == 0 and a[newX][newY] != '#'):
b[newX][newY] = 1
stus[t1].x = newX
stus[t1].y = newY
stus[t1].step = stus[h].step + 1
t1 += 1
if(newX == x1 and newY == y1):
v = 1
break
if v == 1:
break
h += 1
if v == 0:
print(-1)
else:
print(stus[t1 - 1].step)
二.求最小生成树,Prim算法
某省调查乡村交通状况,得到的统计表中列出了任意两村庄间的距离。省政府“畅通工程”的目标是使全省任何两个村庄间都可以实现公路交通(但不一定有直接的公路相连,只要能间接通过公路可达即可),并要求铺设的公路总长度为最小。请计算最小的公路总长度。
测试输入包含若干测试用例。每个测试用例的第1行给出村庄数目N ( < 100 );随后的N(N-1)/2行对应村庄间的距离,每行给出一对正整数,分别是两个村庄的编号,以及此两村庄间的距离。为简单起见,村庄从1到N编号。当N为0时,输入结束,该用例不被处理。
样例输入: 8 1 2 42 1 3 68 1 4 35 1 5 1 1 6 70 1 7 25 1 8 79 2 3 59 2 4 63 2 5 65 2 6 6 2 7 46 2 8 82 3 4 28 3 5 62 3 6 92 3 7 96 3 8 43 4 5 28 4 6 37 4 7 92 4 8 5 5 6 3 5 7 54 5 8 93 6 7 83 6 8 22 7 8 17 0
样例输出:
82
代码实现:
def prim(dist, S):
global n, g, res
S[1] = 1
dist[1] = 0
#放入每个点离集合S最近的距离,第一个回合
for i in range(2, n+1):
dist[i] = min(dist[i], g[1][i])
#接下来寻找离集合S最近的一个点,加进集合S中
for i in range(2, n+1):
#假定为无穷大
temp = 100000
t = -1
for j in range(2, n+1):
if S[j] == 0 and dist[j] < temp:
temp = dist[j]
t = j
#循环出来得到离集合S最近的一个点,加入集合S,更新dist,S列表
S[t] = 1
res += dist[t]
for j in range(2, n+1):
#列表S改变之后,每个点距离集合S的更新
dist[j] = min(dist[j], g[t][j])
while(True):
n = int(input())
if n == 0:
break
res = 0
S = [0] * (n + 1) #存放加入到S中的点集合
dist = [10000] * (n + 1)#存放到集合S的距离
g = [0]*(n + 1)
for i in range(0, n+1):
g[i] = [0] * (n + 1)
m = (n*(n-1))/2
for i in range(0, int(m)):
a, b, c = map(int,input().split(' '))
g[a][b] = g[b][a] = c
prim(dist, S)
print(res)