📌  相关文章
📜  国际空间研究组织 | ISRO CS 2016 |问题 53(1)

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

ISRO CS 2016 Question 53

题目描述

在bunny空间,有一个n x n的方格矩阵,在矩阵的每个单元格具有立方体高度。现在,你被要求选择矩阵中的两个单元格,并且从这些单元格的最短路径中选择最小的高度。找到最小可能高度,使得从一个单元格到另一个单元格的最短路径中没有高于该高度的单元格。请编写一个函数,使用Python实现以下问题。

输入描述

第一行输入n的值,接下来n行输入n个整数来表示矩阵的高度,最后一行输入表示要查询的次数

接下来每行是两个整数,表示起始点和结束点

输出描述

查询询问中,每个询问必须单独输出一行。如果没有高度低于或等于给定高度,则输出“NO PATH FOUND”。否则,输出高度等于或低于给定高度的最短路径。

示例
输入
4
28 25 20 32
34 29 40 47
32 28 33 32
36 27 29 28
3
1 1 3 3
2 3 4 2
4 4 1 4
输出
28
32
NO PATH FOUND
解题思路

这道题目是一个求最短路径的问题,可以用Dijkstra算法或者Floyd算法进行求解。

Dijkstra算法是一种贪心算法,通过不断选取最短路径来更新点的距离,直至找到所需的终点。

Floyd算法是一种动态规划算法,通过不断更新点之间的距离来求解所有点之间的最短路径。

我们可以通过两种算法中的一种来解决这个问题。具体来说,我们可以将矩阵中的每个单元格看作一个节点,并且计算节点之间的距离。对于两个需要查询的节点,我们可以使用Dijkstra算法或Floyd算法来计算它们之间的最短路径,并找到路径上的最小高度。

代码实现
使用Dijkstra算法
from heapq import heappush, heappop
from typing import List

# 计算节点之间的距离
def get_dist(n: int, grid: List[List[int]]) -> List[List[int]]:
    dist = [[float('inf') for _ in range(n)] for _ in range(n)]

    for i in range(n):
        for j in range(n):
            # 计算节点之间的距离
            if i > 0:
                dist[i][j] = min(dist[i][j], abs(grid[i][j] - grid[i - 1][j]))
            if i < n - 1:
                dist[i][j] = min(dist[i][j], abs(grid[i][j] - grid[i + 1][j]))
            if j > 0:
                dist[i][j] = min(dist[i][j], abs(grid[i][j] - grid[i][j - 1]))
            if j < n - 1:
                dist[i][j] = min(dist[i][j], abs(grid[i][j] - grid[i][j + 1]))

    return dist

# 使用Dijkstra算法求解最短路径
def dijkstra(n: int, grid: List[List[int]], src: int, dest: int, h: int) -> int:
    dist = [float('inf') for _ in range(n * n)]
    visited = [False for _ in range(n * n)]
    heap = []

    # 初始化源节点
    dist[src] = 0
    visited[src] = True
    heappush(heap, (0, src))

    while heap:
        min_dist, u = heappop(heap)

        # 找到最短路径
        if u == dest:
            return min_dist

        for v in range(n * n):
            # 计算节点之间的距离
            if get_dist(n, grid)[u // n][u % n][v // n][v % n] <= h and not visited[v]:
                visited[v] = True
                dist[v] = min(dist[v], grid[v // n][v % n])
                heappush(heap, (dist[v], v))

    # 没有找到路径
    return -1

if __name__ == '__main__':
    n = int(input())
    grid = []
    for _ in range(n):
        grid.append(list(map(int, input().split())))
    q = int(input())

    for _ in range(q):
        x1, y1, x2, y2 = map(int, input().split())
        src = (x1 - 1) * n + y1 - 1
        dest = (x2 - 1) * n + y2 - 1
        h = float('inf')

        # 使用二分法查找最小高度
        left, right = 0, max(max(row) for row in grid)
        while left <= right:
            mid = (left + right) // 2
            if dijkstra(n, grid, src, dest, mid) != -1:
                h = min(h, mid)
                right = mid - 1
            else:
                left = mid + 1

        # 输出结果
        if h == float('inf'):
            print('NO PATH FOUND')
        else:
            print(h)
使用Floyd算法
from typing import List

# 计算节点之间的距离
def get_dist(n: int, grid: List[List[int]]) -> List[List[int]]:
    dist = [[float('inf') for _ in range(n * n)] for _ in range(n * n)]

    for i in range(n * n):
        dist[i][i] = 0

        if i % n == 0:
            if i - n >= 0:
                dist[i][i - n] = abs(grid[i // n][i % n] - grid[(i - n) // n][(i - n) % n])
            if i + n < n * n:
                dist[i][i + n] = abs(grid[i // n][i % n] - grid[(i + n) // n][(i + n) % n])
            if i % n != n - 1:
                dist[i][i + 1] = abs(grid[i // n][i % n] - grid[i // n][(i + 1) % n])
        elif i % n == n - 1:
            if i - n >= 0:
                dist[i][i - n] = abs(grid[i // n][i % n] - grid[(i - n) // n][(i - n) % n])
            if i + n < n * n:
                dist[i][i + n] = abs(grid[i // n][i % n] - grid[(i + n) // n][(i + n) % n])
            if i % n != 0:
                dist[i][i - 1] = abs(grid[i // n][i % n] - grid[i // n][(i - 1) % n])
        else:
            if i - n >= 0:
                dist[i][i - n] = abs(grid[i // n][i % n] - grid[(i - n) // n][(i - n) % n])
            if i + n < n * n:
                dist[i][i + n] = abs(grid[i // n][i % n] - grid[(i + n) // n][(i + n) % n])
            dist[i][i + 1] = abs(grid[i // n][i % n] - grid[i // n][(i + 1) % n])
            dist[i][i - 1] = abs(grid[i // n][i % n] - grid[i // n][(i - 1) % n])

    for k in range(n * n):
        for i in range(n * n):
            for j in range(n * n):
                dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j])

    return dist

if __name__ == '__main__':
    n = int(input())
    grid = []
    for _ in range(n):
        grid.append(list(map(int, input().split())))
    q = int(input())

    dist = get_dist(n, grid)

    for _ in range(q):
        x1, y1, x2, y2 = map(int, input().split())
        src = (x1 - 1) * n + y1 - 1
        dest = (x2 - 1) * n + y2 - 1
        h = float('inf')

        # 查找最小高度
        for i in range(256):
            found = False
            for j in range(n * n):
                if dist[src][j] != float('inf') and dist[j][dest] != float('inf') and abs(grid[src // n][src % n] - grid[j // n][j % n]) <= i and abs(grid[j // n][j % n] - grid[dest // n][dest % n]) <= i:
                    h = i
                    found = True
                    break
            if found:
                break

        # 输出结果
        if h == float('inf'):
            print('NO PATH FOUND')
        else:
            print(h)