Python算法:迷宫问题(广度优先,模拟C结构体数组),Prim算法(最小生成树)

小明置身于一个迷宫,请你帮小明找出从起点到终点的最短路程。
小明只能向上下左右四个方向移动。
输入包含多组测试数据。输入的第一行是一个整数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)

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值