Shopee的办公室

1.题目描述

 shopee的办公室非常大,小虾同学的位置坐落在右上角,而大门却在左下角,可以把所有位置抽象为一个网格(门口的坐标为0,0),小虾同学很聪明,每次只向上,或者向右走,因为这样最容易接近目的地,但是小虾同学不想让自己的boss们看到自己经常在他们面前出没,或者迟到被发现。他决定研究一下如果他不通过boss们的位置,他可以有多少种走法?
输入描述:
 第一行 x,y,n (0<x<=30, 0<y<=30, 0<=n<= 20) 表示x,y小虾的座位坐标,n 表示boss的数量( n <= 20)
接下来有n行, 表示boss们的坐标(0<xi<= x, 0<yi<=y,不会和小虾位置重合)
 x1, y1
 x2, y2
 ……
 xn, yn
输出描述:
 输出小虾有多少种走法

2.解题思路

动态规划:

  • 初始化,第一行:如果第一行有boss的话,boss位置之后的坐标位置到达不了
      dp[0][i] = location[0][i]==1 ? 0:dp[0][i-1];
  • 初始化,第一列,如果第一列有boss的话,boss之后的坐标位置到达不了
      dp[i][0] = location[i][0]==1?1:dp[i-1][0];
  • 状态转移方程:
    如果遇到boss,则之前的作废,此时dp[i][j] = 0;否则为现在位置的走法总数=现在位置的左边总数+现在位置的下边总数
      dp[i][j] = location[i][j] == 1 ? 0:dp[i-1][j]+dp[i][j-1];

3.代码

import java.util.Scanner;
public class Main {
    public static void main(String[] args) {
        Scanner sr = new Scanner(System.in);
        int x = sr.nextInt();
        int y = sr.nextInt();
        int n = sr.nextInt();
        int [][] location = new int[x+1][y+1];
        for(int i = 0;i<n;i++){
            int x1 = sr.nextInt();
            int y1 = sr.nextInt();
            if(x1<=x  && y1<=y)
                location[x1][y1] = 1;
        }
        System.out.println(solution(location,x,y));

    }

    private static long solution(int[][] location, int x, int y) {

        long dp[][] = new long[x+1][y+1];
        //行初始化
        dp[0][0] = 1;
        for(int i = 1;i<=y;i++){
           dp[0][i] = location[0][i]==1 ? 0:dp[0][i-1];
        }
        //列初始化
        for(int i = 1;i<=x;i++){
            dp[i][0] = location[i][0]==1?1:dp[i-1][0];
        }
        //动态规划
        for(int i = 1;i<=x;i++){
            for(int j = 1;j<=y;j++){
                dp[i][j] = location[i][j] == 1 ? 0:dp[i-1][j]+dp[i][j-1];
            }
        }
        return dp[x][y];
    }
}

在这里插入图片描述
题型为leetcode-63:不同路径2的应用,
先引入leetcod-62-不同的路径:https://leetcode-cn.com/problems/unique-paths/

1 题目描述

 一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为“Start” )。机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为“Finish”)。问总共有多少条不同的路径?

2.解题思路

  • (1)初始化

    •  1) 从[0,0]走到[0,0]的路径,即没走,设dp[0][0] = 0;
    •  2) 如果mn的n为1,即机器人在m1走,只能有一条路径,即dp[i][0] = 1;
    •  3) 如果mn的m为1,即机器人在1n走,只能有一条路径,即dp[0][i] = 1;
  • (2) 动态规划核心算法

  • 机器人每次只能向下或者向右移动一步。即机器人dp[i][j]的路径由dp[i-1][j]和dp[i][j-1]决定,即

    • dp[i][j] = dp[i-1][j]+dp[i][j-1]

3.代码

class Solution {
 public static int uniquePaths(int m, int n) {
        if(m < 0 || n < 0)
            return 0;
        int dp[][] = new int[m][n];
        //初始化
        dp[0][0] = 0;
        //初始化列
        for(int i = 0;i<n;i++){
            dp[0][i] = 1;
        }
        //初始化行
        for(int i = 0;i<m;i++){
            dp[i][0] = 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];
    }
}

leetcode-63:不同路径2:https://leetcode-cn.com/problems/unique-paths-ii/

1.题目描述

  一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为“Start” )。机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为“Finish”)。现在考虑网格中有障碍物。那么从左上角到右下角将会有多少条不同的路径?网格中的障碍物和空位置分别用 1 和 0 来表示。说明:m 和 n 的值均不超过 100。
示例 1:
输入:

 [
 [0,0,0],
 [0,1,0],
 [0,0,0]
 ]
输出:
  2
解释:
 3x3 网格的正中间有一个障碍物。
 从左上角到右下角一共有 2 条不同的路径:
  向右 -> 向右 -> 向下 -> 向下
  向下 -> 向下 -> 向右 -> 向右

2.解题思路

 如果第一个格点 obstacleGrid[0][0] 是 1,说明有障碍物,那么机器人不能做任何移动,我们返回结果 0。如果 obstacleGrid[0][0] 是 0,我们初始化这个值为 0 然后继续算法。

  • (1)动态规划初始化
    •  1)obstacleGrid[0][0] == 0,表示没障碍,路径只有一条;
               dp[0][0] = 1;
    •  2)遍历第一行,如果有一个格点初始值为 1 ,说明当前节点有障碍物,没有路径可以通过,设值为 0 ;否则设这个值是前一个节点的值
                dp[0][j] = dp[0][j-1]
    •  3)遍历第一列,如果有一个格点初始值为 1 ,说明当前节点有障碍物,没有路径可以通过,设值为 0 ;否则设这个值是前一个节点的值
                dp[i][0] = obstacleGrid[i-1][0]
  • (2) 动态规划核心算法
     从 obstacleGrid[1][1] 开始遍历整个数组,如果某个格点初始不包含任何障碍物,就把值赋为上方和左侧两个格点方案数之和
             dp[i][j] = dp[i-1][j] + dp[i][j-1]
    如果这个点有障碍物,设值为 0 ,dp[i][j] = 0;这可以保证不会对后面的路径产生贡献。

3.代码

class Solution {
      public int uniquePathsWithObstacles(int[][] obstacleGrid) {
        int row = obstacleGrid.length;
        int col = obstacleGrid[0].length;
        if(obstacleGrid[0][0] == 1 || obstacleGrid==null){
            return 0;
        }
        int dp[][] = new int[row][col];
        dp[0][0] = 1;
        //行初始化
        for(int i = 1;i<col;i++){
            dp[0][i] = obstacleGrid[0][i]==1 ? 0 : dp[0][i-1];
        }
        //列初始化
        for(int i = 1;i<row; i++){
            dp[i][0] = obstacleGrid[i][0] == 1? 0:dp[i-1][0];
        }
        //动态规划
        for(int i = 1;i<row;i++){
            for(int j = 1;j<col;j++){
                    dp[i][j] = obstacleGrid[i][j] == 1 ? 0 : dp[i-1][j]+dp[i][j-1];
            }
        }
        return dp[row-1][col-1];
    }
}
  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值