📜  算法测验| SP竞赛3 |问题5(1)

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

算法测验 | SP竞赛3 | 问题5

这是一道关于算法的测验问题,属于SP竞赛的第三个问题。本问题需要程序员熟悉搜索算法和动态规划算法。

问题描述

给定一个 $n \times m$ 的矩阵,矩阵中的每个元素都是非负整数。从第一行第一个元素开始出发,每次只能向右或者向下走,目标是到达最后一行最后一个元素,使得经过的路径上的数字之和最小。

输入格式

第一行包含两个整数 $n, m$。

接下来 $n$ 行,每行 $m$ 个整数,表示矩阵中的元素。

输出格式

一个整数,表示满足要求的使经过的路径上的数字之和最小的路径数字之和。

样例输入
3 3
1 3 1
1 5 1
4 2 1
样例输出
7
分析与解法

对于这道题目,我们可以利用动态规划算法来解决。我们定义 $f[i][j]$ 表示从 $(1,1)$ 到 $(i,j)$ 的最小路径和,则有状态转移方程:

$$ f[i][j]=\min(f[i-1][j],f[i][j-1])+a[i][j] $$

其中 $a[i][j]$ 表示第 $i$ 行,第 $j$ 列的元素。我们可以根据这个动态规划方程来求解最小路径和。

另外,我们也可以利用Dijkstra算法来解决该问题。可以将每个格子看成一个节点,每个节点之间的边权为两个节点值的和。这样就可以构成一个图,利用Dijkstra算法求解最短路径。

代码实现

动态规划的实现:

n, m = map(int, input().split())

a = []
for i in range(n):
    a.append(list(map(int, input().split())))

f = [[0x7fffffff for j in range(m)] for i in range(n)]
f[0][0] = a[0][0]

for i in range(n):
    for j in range(m):
        if i > 0:
            f[i][j] = min(f[i][j], f[i-1][j]+a[i][j])
        if j > 0:
            f[i][j] = min(f[i][j], f[i][j-1]+a[i][j])

print(f[n-1][m-1])

Dijkstra算法的实现:

import heapq

n, m = map(int, input().split())

a = []
for i in range(n):
    a.append(list(map(int, input().split())))

g = [[] for i in range(n*m)]
for i in range(n):
    for j in range(m):
        x = i * m + j
        if i < n-1:
            y = (i+1)*m+j
            g[x].append((y, a[i+1][j]))
            g[y].append((x, a[i][j]))
        if j < m-1:
            y = i*m+j+1
            g[x].append((y, a[i][j+1]))
            g[y].append((x, a[i][j]))

dist = [0x7fffffff for i in range(n*m)]
dist[0] = a[0][0]

heap = [(dist[0], 0)]
while heap:
    d, x = heapq.heappop(heap)
    if dist[x] < d:
        continue
    for t in g[x]:
        y, w = t
        if dist[y] > dist[x] + w:
            dist[y] = dist[x] + w
            heapq.heappush(heap, (dist[y], y))

print(dist[n*m-1])