首页 > 其他分享 >动态规划-路径问题

动态规划-路径问题

时间:2022-11-01 09:58:08浏览次数:93  
标签:格子 int 路径 ++ grid 动态 规划 dp

动态规划是一种通过把原问题分解为相对简单的子问题的方式求解复杂问题的方法,常常适用于有重叠子问题最优子结构性质的问题,并且记录所有子问题的结果,因此动态规划方法所耗时间往往远少于朴素的穷举解法。

动态规划有自底向上和自顶向下两种解决问题的方式。自顶向下即记忆化递归,自底向上就是递推。

使用动态规划解决的问题有个明显的特点:无后效性,一旦一个子问题的求解得到结果,以后的计算过程就不会修改它。

我们以一个简单的路径问题,来解锁下动态规划的解题思路

1.一个棋子位于一个 m x n 棋盘的左上角 ,棋子每次只能向下或者向右移动一步。如果将棋子从左上角移动到右下角,

问总共有多少条不同的路径?

一般人在没有了解动态规划之前,处理这种问题只能靠穷举所有路线得到结果。

但是穷举可能会漏会重,在mxn的数字比较大时,耗时很长且非常容易出错。

那动态规划如何解决这个问题呢?我们先画个图

s      
       
       
      e

如上图所示,棋子要从棋盘的s位置,移动到e,而且只能向下或向右移动,每次移动一步。

那我们返回来思考,假如棋子已经移动到e,那么他是从哪里过来的呢?

显而易见,只能从左边格子或者上边格子,即两个我们标蓝色的格子。

那我们可以定义f(i,j)为从s移动到e的所有路径的总和。那么f(i,j)=f(i-1,j)+f(i,j-1)

这就是我们的动态转移方程。

接下来上代码

class Solution {
   public int uniquePaths(int m, int n) {
       //定义dp数组
        int[][] dp = new int[m ][n ];
      //第一行,第一列的位置,都只有唯一一种路径
        for (int i = 0; i < m; i++) {
            dp[i][0] = 1;
        }
        for (int j = 0; j < n; j++) {
            dp[0][j] = 1;
        }
        for (int i = 1; i < m; i++) {
            for (int j = 1; j < n; j++) {
                //通过子问题的结果,推导出上一层问题的结果
                dp[i][j] = dp[i - 1][j] + dp[i][j - 1];
            }
        }
        return dp[m-1][n-1];
    }
}

 

2.最小路径和,给定一个包含非负整数的 m x n 棋盘 ,棋盘的每个格子都有一个数字,请找出一条从左上角到右下角的路径,使得路径上的数字总和为最小。

说明:每次只能向下或者向右移动一步。

1 3 1
1 5 1
4 2 1

 

这个题目跟上一个非常类似,只是不再求路径总数,而是要求一个最小的路径和。

其实思路是一样的,我们假设我们已经达到右下角,那么来路无非还是两个左边的格子和上边的格子,

假设到达这两个格子的最小路径分别是left,top。

为了求最小路径,我们需要比较下left和top的大小,然后取较小的哪一个,然后再加上当前格子的值,就是右下角的最小路径和

假设f(i,j)是位置i,j的最小路径和,nums[i,j]是位置i,j的数字,那么我们就得到了动态转移方程:

f(i,j)=min{f(i,j-1),f(i-1,j)}+nums[i,j]

class Solution {
    public int minPathSum(int[][] grid) {
        int m = grid.length;
        int n = grid[0].length;
        int[][] dp = new int[m][n];
        //dp第一列等于grid第一列的累计和
        int total1 = 0;
        for (int i = 0; i < m; i++) {
            total1 += grid[i][0];
            dp[i][0] = total1;
        }
        int total2 = 0;
        //dp第一行等于grid第一行的累计和
        for (int j = 0; j < n; j++) {
            total2 += grid[0][j];
            dp[0][j] = total2;
        }
        for (int i = 1; i < m; i++) {
            for (int j = 1; j < n; j++) {
                dp[i][j] = Math.min(dp[i - 1][j], dp[i][j - 1]) + grid[i][j];
            }
        }
        return dp[m - 1][n - 1];
    }
}
        

 

标签:格子,int,路径,++,grid,动态,规划,dp
From: https://www.cnblogs.com/wangbin2188/p/16846702.html

相关文章

  • c# 动态添加属性字段
    上来先吐槽一波,近一段时间公司为搞跨平台的客户端,我的wpf客户端逐渐被放弃,我的工作也越来越少,新的客户端采用qt来做,也有可能是qt开发进度太慢,项目比较紧,于是想让我的客......
  • js 如何给一个对象,动态添加属性字段
    第一种方法:无指定属性letobj={"name":"tom","age":16}letkey="id";letvalue=2obj[key]=value;console.log(obj)第二种方法,利用扩展运算符,简单又实用无......
  • cross socket ssl动态库
    crosssocketssl动态库crosssocket支持ssl需要动态库的支持,它的源码注释就说得很清楚。unitNet.OpenSSL;{OpenSSL下载:https://indy.fulgan.com/SSL/htt......
  • cmake-静态库&动态库
    静态库动态库......
  • 力扣 113. 路径总和 II [dfs,bfs]
    113.路径总和II给你二叉树的根节点 root 和一个整数目标和 targetSum ,找出所有 从根节点到叶子节点 路径总和等于给定目标和的路径。叶子节点是指没有子节......
  • Mybatis动态sql
    通过Mybatis提供的各种标签方法实现动态拼接sql。需求:根据性别和名字查询用户信息。原生sql:SELECTid,username,birthday,sex,addressFROM`user`WHEREsex=1......
  • 微信小程序动态增加组件(以按钮为例)
    这里的微信小程序动态加载是以按钮为例,主页面点击不同的按钮进入不同的子页面中,根据主页面的title来动态加载子页面按钮的数量以及值。效果图:wxml文件(注意wx:key="item"要写......
  • 无法定位序数4540于动态链接库LIBEAY32.dll上(以及其它无法定位序数的解决方案)
    1、程序依赖于libeay32.dll动态链接库时:创建脚本:@echo开始注册copylibeay32.dll%windir%\system32\regsvr32%windir%\system32\libeay32.dll/[email protected]注......
  • Dijkstra最短路径算法
    概念是从一个顶点到其余各顶点的最短路径算法,解决的是有权图中最短路径问题。迪杰斯特拉算法主要特点是从起始点开始,采用贪心算法的策略,每次遍历到始点距离最近且未访问过......
  • [Telink][TLSR8251] [泰凌微][SDK3.4] 添加广播内容 和 动态广播 厂商信息
    添加广播内容。这种直接把内容广播出去,发现者不必连接就能获取数据。广播类型/**@defgroupBLE_GAP_AD_TYPE_DEFINITIONSGAPAdvertisingandScanResponseDataformat*......