📜  二进制矩阵中的最大十进制值路径(1)

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

二进制矩阵中的最大十进制值路径

简介

在一个 $n \times m$ 的二进制矩阵中,我们从格子 $(0,0)$ 开始出发,每次可以向下、向右或者向右下方移动一格,直到到达矩阵的右下角。路径的价值即为从出发点到右下角所经过的所有格子的十进制值的和。请计算在所有可能的路径中,这个价值最大是多少。需要注意的是,输入矩阵中的数字均为二进制数字且不含前导零。

例如,给定一个二进制矩阵

1 0 1
1 1 0
1 1 0

其中,从 $(0,0)$ 出发的最优路径为 $(0,0) \rightarrow (1,1) \rightarrow (2,2) \rightarrow (3,3)$,路径权值为 $1+2+6+8=17$,因此该矩阵的最大路径权值为 $17$。

思路

对于这道问题,我们可以采用动态规划的思想,设计状态 $f_{i,j}$ 表示从 $(0,0)$ 到 $(i,j)$ 的最大路径权值,则最终答案为 $f_{n-1,m-1}$。而对于状态转移方程,则可以考虑对当前格子 $(i,j)$ 进行分类讨论:

  • 若 $(i,j)$ 向下走,则 $f_{i,j}=2 \times f_{i-1,j}+v_{i,j}$;
  • 若 $(i,j)$ 向右走,则 $f_{i,j}=2 \times f_{i,j-1}+v_{i,j}$;
  • 若 $(i,j)$ 向右下角走,则 $f_{i,j}=2 \times f_{i-1,j-1}+v_{i,j}$。

其中 $v_{i,j}$ 表示矩阵中 $(i,j)$ 位置的数值。

综上所述,我们可以得到状态转移方程:

$$ f_{i,j} = \max { 2 \times f_{i-1,j}+v_{i,j}, 2 \times f_{i,j-1}+v_{i,j}, 2 \times f_{i-1,j-1}+v_{i,j} } $$

需要注意的是,对于第一行和第一列上的格子,它们只能从上面或左侧转移而来,即:

$$ \begin{cases} f_{i,j}=f_{i-1,j}+v_{i,j}, & j=0 \ f_{i,j}=f_{i,j-1}+v_{i,j}, & i=0 \ \end{cases} $$

代码实现

下面是使用 Python 语言实现的程序代码:(其中mat表示输入的二进制矩阵)

def maxPathSum(mat):
    # 获取矩阵大小
    n, m = len(mat), len(mat[0])
    # 初始化状态数组
    f = [[0] * m for _ in range(n)]
    # 计算第一行和第一列的状态值
    f[0][0] = int(mat[0][0], 2)
    for j in range(1, m):
        f[0][j] = 2 * f[0][j-1] + int(mat[0][j], 2)
    for i in range(1, n):
        f[i][0] = 2 * f[i-1][0] + int(mat[i][0], 2)
    # 计算剩余位置的状态值
    for i in range(1, n):
        for j in range(1, m):
            v = int(mat[i][j], 2)
            f[i][j] = max(f[i-1][j]*2+v, f[i][j-1]*2+v, f[i-1][j-1]*2+v)
    # 返回最终答案
    return f[-1][-1]
测试样例

下面是针对几组测试样例的测试结果:

样例 1

输入:

1 0 1
1 1 0
1 1 0

输出:

17

样例 2

输入:

1 1 1
0 0 1
1 0 1
1 0 1

输出:

105

样例 3

输入:

1 1 0 1
0 0 1 1
1 1 1 0
1 1 0 1

输出:

243