1.递归方式
求最短,最终状态即右下角

f(v, i, j) = min(f(v, i - 1, j), f(v, i, j - 1)) + v[i][j]

最长只需将min改为max即可

import numpy as np
# i:行
# j:列
# v:矩阵


def f(v, i, j):
    if i == 0 and j == 0:
        return v[0][0]
    elif i == 0:
        return f(v, i, j - 1) + v[i][j]
    elif j == 0:
        return f(v, i - 1, j) + v[i][j]
    else:
        return min(f(v, i - 1, j), f(v, i, j - 1)) + v[i][j]


v = np.array([[1, 3, 5, 9], [8, 1, 3, 4], [5, 0, 6, 1], [8, 8, 4, 0]])
print(f(v, 3, 3))

2.递推方式
注意到只能往右或往下,可以想象,每下一层是右方或下方,而矩阵中,可以想象是以平行与对角线方向为一层,一层层从左上角到右下角递推
即运行一半为如此:

运行完全部为如此

而一层层,每层每一单元取左或上累计最少的数加上本身

f[i][j] = min(f[i - 1]f[j], f[i]f[j - 1]) + v[i][j]

因此:代码如下:

import numpy as np
# i:行
# j:列
# v:矩阵


def f(v, n):
    s = np.array([[0] * n] * n)
    for p in range(n):
        for i in range(p + 1):
            j = p - i
            if i == 0 and j == 0:
                s[0][0] = v[0][0]
            elif i == 0:
                s[0][j] = s[0][j - 1] + v[0][j]
            elif j == 0:
                s[i][0] = s[i - 1][0] + v[i][0]
            else:
                s[i][j] = min(s[i - 1][j], s[i][j - 1]) + v[i][j]
    limit = 0
    for p in range(n, 2 * n - 1):
        limit += 1
        for i in range(limit, p - limit + 1):
            j = p - i
            if i == 0 and j == 0:
                s[0][0] = v[0][0]
            elif i == 0:
                s[0][j] = s[0][j - 1] + v[0][j]
            elif j == 0:
                s[i][0] = s[i - 1][0] + v[i][0]
            else:
                s[i][j] = min(s[i - 1][j], s[i][j - 1]) + v[i][j]
    return s


v = np.array([[1, 3, 5, 9], [8, 1, 3, 4], [5, 0, 6, 1], [8, 8, 4, 0]])
print(f(v, 4))

最后统计出的矩阵的右下即为最少路径和(s[n-1][n-1])

而通过返回s[n-1],我们可以看到路径,从左上角开始,取每一层最小值(不可单独面对方向,可能会陷入陷阱,中途进入错误路径),代码实现如下:

def view(s, n):
    string = ''
    for p in range(n):
        min = 0
        for i in range(p + 1):
            j = p - i
            if min == 0:
                min = s[i][j]
            elif min > s[i][j]:
                min = s[i][j]
        string += str(min) + '->'
    limit = 0
    for p in range(n, 2 * n - 1):
        limit += 1
        min = 0
        for i in range(limit, p - limit + 1):
            j = p - i
            if min == 0:
                min = s[i][j]
            elif min > s[i][j]:
                min = s[i][j]
        if p == (2 * n - 2):
            string += str(min)
        else:
            string += str(min) + '->'
    return string

原矩阵:

运行效果:

01-06 17:43