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
原矩阵:
运行效果: