📜  门| GATE CS Mock 2018年|套装2 |第65章(1)

📅  最后修改于: 2023-12-03 15:12:38.390000             🧑  作者: Mango

门 | GATE CS Mock 2018年|套装2 |第65章

本次考试的主题是“门”,主要考察程序员在门类问题的解决方案和实现能力。以下是关于本次考试的介绍和参考思路。

题目描述

本次考试涉及到两个问题:

  1. 在一个N x M的网格图中,有一些门和障碍物。假设你从(0,0)出发,最少需要多少步才能到达目的地(N-1, M-1)。
  2. 在一个有向图中,有n个门和几条边。给出q次询问,每次询问查找从门u到门v的最短路径长度。
参考思路
问题1

这个问题可以用最短路径算法来解决。常见的算法有:

  • Dijkstra算法
  • Bellman-Ford算法
  • Floyd-Warshall算法
  • A*算法

其中,A算法可能更适合这个问题。因为它可以在很短的时间内找到最短路径,并且对于复杂的网格图,它也可以给出较好的近似解。但是,需要注意的是,A算法可能会受到启发式函数的影响,导致不一定能找到全局最优解。

问题2

这个问题可以用最短路径算法来解决。同样,常见的算法有:

  • Dijkstra算法
  • Bellman-Ford算法
  • Floyd-Warshall算法

其中,Floyd-Warshall算法可以在O(n^3)的时间复杂度内解决所有的询问。但是,需要注意的是,对于非常大的有向图,Floyd-Warshall算法可能会受到空间限制,导致无法实现。

如果需要快速的解决方案,可以考虑使用Dijkstra算法或者Bellman-Ford算法。这两个算法都需要预处理一遍,然后可以在较短的时间内解决每个询问。

参考代码
问题1
def a_star(start, end, graph):
    def heuristic(n1, n2):
        return abs(n1[0] - n2[0]) + abs(n1[1] - n2[1])
  
    open_list = set([start])
    closed_list = set()
  
    g = {}
    g[start] = 0
  
    parents = {}
    parents[start] = start
  
    while len(open_list) > 0:
        n = None
        for v in open_list:
            if n == None or g[v] + heuristic(v, end) < g[n] + heuristic(n, end):
                n = v;
        
        if n == None:
            print('Path does not exist!')
            return None
  
        if n == end:
            path = []
  
            while parents[n] != n:
                path.append(n)
                n = parents[n]
            path.append(start)
  
            path.reverse()
  
            print('Path found: {}'.format(path))
            return path
  
        for (m, weight) in graph[n]:
            if m not in open_list and m not in closed_list:
                open_list.add(m)
                parents[m] = n
                g[m] = g[n] + weight
  
            else:
                if g[m] > g[n] + weight:
                    g[m] = g[n] + weight
                    parents[m] = n
  
                    if m in closed_list:
                        closed_list.remove(m)
                        open_list.add(m)
  
        open_list.remove(n)
        closed_list.add(n)
  
    print('Path does not exist!')
    return None
问题2
def bellman_ford(graph, start):
    #initialize distance to all vertices as infinite and distance to source as 0
    distance = {v: float('infinity') for v in graph}
    distance[start] = 0
  
    #relax all edges |V| - 1 times, where |V| is the number of vertices
    for i in range(len(graph)-1):
        for u in graph:
            for v, w in graph[u]:
                if distance[u] + w < distance[v]:
                    distance[v] = distance[u] + w
    
    return distance
  
def shortest_path(graph, start, end):
    dist = bellman_ford(graph, start)
    path = []
  
    while end != start:
        path.append(end)
        end = dist[end][1]
  
    path.append(start)
    path.reverse()  
    return path