当前位置: 首页 > news >正文

每日一题(8) 求解矩阵最小路径和问题

给定一个m行n列的矩阵,从左上角开始每次只能向右或者向下移动,最后到达右下角的位置,路径上的所有数字累加起来作为这条路径的路径和。求所有路径和中最小路径和。

输入格式:

首先输入行数m及列数n,接下来输入m行,每行n个数。

输出格式:

输出第一行为最小路径(假定测试数据中的最小路径唯一),第2行为最小路径和。

输入样例1:

4 4
1 3 5 9
8 1 3 4
5 0 6 1
8 8 4 0

输出样例1:

1 3 1 0 6 1 0 
12

问题分析

这是一个典型的路径规划问题,可以使用动态规划来解决。我们需要找到从矩阵左上角到右下角的最小路径和,并记录下这条路径。

在每个点上,我们只能向右或向下移动,因此到达位置 (i, j) 的路径只能来自于位置 (i-1, j)(上方)或位置 (i, j-1)(左方)。我们选择这两个来源中路径和较小的那个,然后加上当前位置的值,即可得到到达 (i, j) 的最小路径和。

解题思路

动态规划解法

我们定义:

  • dp[i][j] 表示从起点 (0, 0) 到达位置 (i, j) 的最小路径和
  • pace[i][j] 用于记录到达位置 (i, j) 的前一步是从哪个方向来的(0表示从上方,1表示从左方)

状态转移方程为:

dp[i][j] = min(dp[i-1][j], dp[i][j-1]) + num[i][j]

边界条件:

  • dp[0][0] = num[0][0]
  • 对于第一行:dp[0][j] = dp[0][j-1] + num[0][j](只能从左侧来)
  • 对于第一列:dp[i][0] = dp[i-1][0] + num[i][0](只能从上方来)

计算完 dp 数组后,dp[m-1][n-1] 就是我们要求的最小路径和。

为了重建最小路径,我们使用 pace 数组记录每一步的选择,然后用栈存储从终点回溯到起点的路径,最后输出即可得到完整路径。

代码实现

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;
public class Main {public static void main(String[] args) throws IOException {BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));StringTokenizer st = new StringTokenizer(bf.readLine());int m = Integer.parseInt(st.nextToken());int n = Integer.parseInt(st.nextToken());int[][] num = new int[m][n];for(int i=0;i<m;i++){st = new StringTokenizer(bf.readLine());for(int j=0;j<n;j++){num[i][j] = Integer.parseInt(st.nextToken());}}int[][] dp = new int[m][n];int[][] pace = new int[m][n];dp[0][0] = num[0][0];//初始化第一行和第一列for(int i=1;i<m;i++){dp[i][0] = num[i][0] + dp[i-1][0];pace[i][0] = 0;}for(int i=1;i<n;i++){dp[0][i] = num[0][i] + dp[0][i-1];pace[0][i] = 1;}//状态转移方程//dp[i][j] = min(dp[i-1][j], dp[i][j-1]) + num[i][j];for(int i=1;i<m;i++){for(int j=1;j<n;j++){if(dp[i-1][j]<dp[i][j-1]){dp[i][j] = dp[i-1][j] + num[i][j];pace[i][j] = 0;}else{dp[i][j] = dp[i][j-1] + num[i][j];pace[i][j] = 1;}}}//逆推路径Stack<Integer> temp = new Stack<>();int i=m-1,j=n-1;while (i>0||j>0){temp.push(num[i][j]);if(pace[i][j]==0) i--;else j--;}temp.push(num[0][0]);while (!temp.isEmpty()){System.out.print(temp.pop()+" ");}System.out.println();System.out.println(dp[m-1][n-1]);}
}

这种方法的时间复杂度为 O(m×n),空间复杂度也为 O(m×n),其中 m 和 n 分别是矩阵的行数和列数。 

相关文章:

  • Debian服务器环境下env变量丢失怎么办
  • yocto编译使用共享缓存
  • gbdt总结
  • Mac 选择下载安装工具 x86 还是 arm64 ?
  • Git学习之路(Updating)
  • 多模态大语言模型arxiv论文略读(二十六)
  • mac上安装VMWare Fusion安装ubuntu系统问题
  • 微带线的损耗
  • pip 的包下载之后存放在哪?
  • CPU、GPU 并行加速
  • hadoop的三大结构及其各自的作用
  • 面试经验杂谈
  • uniapp中uni-easyinput 使用@input 不改变绑定的值
  • Python(21)Python日期时间完全指南:从基础到实战注意事项
  • c加加重点学习之day03
  • 自动驾驶安全模型研究
  • Excel提取图片并自动上传到文件服务器(OOS),获取文件链接
  • 零基础玩转AI数学建模:从理论到实战
  • 【MATLAB代码例程】AOA与TOA结合的高精度平面地位,适用于四个基站的情况,附完整的代码
  • Spring MVC 初体验~~
  • 价格周报|本周生猪均价环比上涨,交易均重继续上升
  • 恒安集团创始人许连捷逝世:白手起家缔造百亿纸品巨头,个人曾捐赠超10亿
  • 湖北一季度GDP为13543.49亿元,同比增长6.3%
  • 2025年青年普法志愿者法治文化基层行活动启动
  • “雪豹瘫痪”“漂流小孩哥大闹幼儿园”都是谣言!10起典型案例公布
  • 体坛联播|曼联加时赛神奇逆转,晋粤大战CBA再出重磅罚单