📜  门| GATE-CS-2017(Set 2)|问题25(1)

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

题目

Gate-CS-2017(Set 2) - 问题25

简介

本题是Gate-CS-2017(Set 2)的第25个问题。本题考察的是动态规划的思想,要求我们求一个二维矩阵中的最长递增路径长度。

问题描述

有一个矩阵$M$,$M(i,j)$表示矩阵中第$i$行第$j$列的元素。我们可以从矩阵中任何一个格子出发,每次沿着上下左右四个方向走一步,但是不能走到越界的格子,也不能走到比当前位置小的格子。例如,如果当前位置是$(x,y)$,那么下一步只能是$(x-1,y)$、$(x+1,y)$、$(x,y-1)$或$(x,y+1)$中比$(x,y)$大的一个位置。求矩阵中最长的满足上述要求的路径的长度。

例如,如果矩阵为:

| 1 | 2 | 6 | | - | - | - | | 5 | 3 | 7 | | 9 | 8 | 4 |

那么最长的路径为$[1,2,3,4,7,8,9]$,长度为$7$。

思路

这是一道典型的动态规划问题。我们可以考虑定义状态来表示最优解中一个子问题的解(例如,$(x,y)$开始的最优解等价于以$(x+1,y)$开始的最优解),然后将最优解分解为子问题的最优解。定义$len(i,j)$表示以$(i,j)$为起点的最长路径长度,可以采用以下的状态转移方程:

$$len(i,j)=1+\max(len(i-1,j),len(i+1,j),len(i,j-1),len(i,j+1))$$

由于动态规划需要遍历表格多次,因此可以采用一些优化策略来避免重复计算,例如用一个$visited$矩阵来记录已经求过的值,避免重复计算。最终的最长路径长度就是所有$len(i,j)$中的最大值。

代码

下面给出一个Python实现的代码片段,采用了优化策略:

def longest_path(matrix):
    # 初始化visited矩阵
    visited = [[False] * len(matrix[0]) for _ in range(len(matrix))]
    ans = 0
    for i in range(len(matrix)):
        for j in range(len(matrix[0])):
            if not visited[i][j]:
                ans = max(ans, dfs(matrix, visited, i, j))
    return ans

def dfs(matrix, visited, i, j):
    # visited矩阵用来剪枝,避免重复计算
    if visited[i][j]:
        return 0

    max_len = 0
    for x, y in [(i-1,j), (i+1,j), (i,j-1), (i,j+1)]:
        if 0 <= x < len(matrix) and 0 <= y < len(matrix[0]) \
                and matrix[x][y] > matrix[i][j]:
            # 递归求解子问题
            max_len = max(max_len, dfs(matrix, visited, x, y))
    visited[i][j] = True

    # 加1表示当前位置可以作为路径上的一个节点
    return 1 + max_len

具体的解释见注释。