算法----Unique Paths

Unique Paths

A robot is located at the top-left corner of a m x n grid (marked 'Start' in the diagram below).

The robot can only move either down or right at any point in time. The robot is trying to reach the bottom-right corner of the grid (marked 'Finish' in the diagram below).

How many possible unique paths are there?


Above is a 7 x 3 grid. How many possible unique paths are there?

Note: m and n will be at most 100.

Example 1:Input: m = 3, n = 2 Output: 3 Explanation: From the top-left corner, there are a total of 3 ways to reach the bottom-right corner: 1. Right -> Right -> Down 2. Right -> Down -> Right 3. Down -> Right -> Right

Example 2:Input: m = 7, n = 3 Output: 28

从起始点出发到达终点,可以向右,向下方向移动,求解从起始点到达终点有多少种解法。

利用dp[m][n]来保存从起始点到达每一个位置的解法数量

考虑第一行i=0的每一个位置,都只有一种方式到达,向右。

考虑第一列j=0的每一个位置,都只有一种方式到达,向下。

考虑i>0,j>0,对于每一个位置(i,j)其可以通过(i-1,j)向下来到达,也可以通过(i,j-1)向右来到达,因此有dp[i][j]=dp[i-1][j]+dp[i][j-1];

public int uniquePaths(int m, int n) {
        int[][] dp = new int[n][m];
        for(int i=0; i<n; i++){
            dp[i][0] = 1;
        }
        for(int j=0; j<m; j++){
            dp[0][j] = 1;
        }
        for(int i=1; i<n; i++){
            for(int j=1; j<m; j++){
                dp[i][j] = dp[i-1][j] + dp[i][j-1];
            }
        }
        return dp[n-1][m-1];
}

Unique Paths II

A robot is located at the top-left corner of a m x n grid (marked 'Start' in the diagram below).

The robot can only move either down or right at any point in time. The robot is trying to reach the bottom-right corner of the grid (marked 'Finish' in the diagram below).

Now consider if some obstacles are added to the grids. How many unique paths would there be?

An obstacle and empty space is marked as 1 and 0 respectively in the grid.

Note: m and n will be at most 100.

Example 1:Input: [   [0,0,0],   [0,1,0],   [0,0,0] ] Output: 2 Explanation: There is one obstacle in the middle of the 3x3 grid above. There are two ways to reach the bottom-right corner: 1. Right -> Right -> Down -> Down 2. Down -> Down -> Right -> Right

从起始点到达终点,路上可能存在障碍,求解出发点到达终点的解法数量。

如果出发点obstacleGrid[0][0]==1有障碍,则直接返回0即可,不可能到达终点;

对于第一行除起始位置其他元素dp[0][j]来说,如果没有障碍,则可以通过左边位置dp[0][j-1]向右到达,因此dp[0][j] = dp[0][j-1];如果有障碍,则该位置dp[0][j]=0;

同理,对于第一列除起始位置来说,无障碍  dp[i][0] = dp[i-1][0];  有障碍  dp[i][0]=0;

对于i>0,j>0  无障碍 dp[i][j] = dp[i-1][j] + dp[i][j-1];  有障碍  dp[i][j]=0;

public int uniquePathsWithObstacles(int[][] obstacleGrid) {
        int n = obstacleGrid.length;
        int m = obstacleGrid[0].length;
        int[][] dp = new int[n][m];
        if(obstacleGrid[0][0]==1)
            return 0;
        dp[0][0] = 1;
        for(int i=1; i<n; i++){
            if(obstacleGrid[i][0]==0)
                dp[i][0] = dp[i-1][0];
        }
        for(int j=1; j<m; j++){
            if(obstacleGrid[0][j]==0)
                dp[0][j] = dp[0][j-1];
        }
        for(int i=1; i<n; i++){
            for(int j=1; j<m; j++){
                if(obstacleGrid[i][j]==0)
                    dp[i][j] = dp[i-1][j] + dp[i][j-1];
            }
        }
        return dp[n-1][m-1];
    }

Unique Paths III

On a 2-dimensional grid, there are 4 types of squares:

  • 1 represents the starting square.  There is exactly one starting square.
  • 2 represents the ending square.  There is exactly one ending square.
  • 0 represents empty squares we can walk over.
  • -1 represents obstacles that we cannot walk over.

Return the number of 4-directional walks from the starting square to the ending square, that walk over every non-obstacle square exactly once.

Example 1:Input: [[1,0,0,0],[0,0,0,0],[0,0,2,-1]] Output: 2 Explanation: We have the following two paths: 1. (0,0),(0,1),(0,2),(0,3),(1,3),(1,2),(1,1),(1,0),(2,0),(2,1),(2,2) 2. (0,0),(1,0),(2,0),(2,1),(1,1),(0,1),(0,2),(0,3),(1,3),(1,2),(2,2)

Example 2:Input: [[1,0,0,0],[0,0,0,0],[0,0,0,2]] Output: 4 Explanation: We have the following four paths: 1. (0,0),(0,1),(0,2),(0,3),(1,3),(1,2),(1,1),(1,0),(2,0),(2,1),(2,2),(2,3) 2. (0,0),(0,1),(1,1),(1,0),(2,0),(2,1),(2,2),(1,2),(0,2),(0,3),(1,3),(2,3) 3. (0,0),(1,0),(2,0),(2,1),(2,2),(1,2),(1,1),(0,1),(0,2),(0,3),(1,3),(2,3) 4. (0,0),(1,0),(2,0),(2,1),(1,1),(0,1),(0,2),(0,3),(1,3),(1,2),(2,2),(2,3)

Example 3:Input: [[0,1],[2,0]] Output: 0 Explanation: There is no path that walks over every empty square exactly once. Note that the starting and ending square can be anywhere in the grid.

1代表起始点,2代表终点,0代表无障碍,-1代表有障碍    移动方向可以上下左右

求从起始点到达终点的可以访问所有无障碍位置的路径解法数量。

 

利用dfs深度优先搜索来寻找所有可能路径

首先遍历grid找到起始点,终点以及无障碍位置总数;

从起始点位置沿四个方向开始进行dfs搜索;

    判断当前位置是否为终点,如果是终点,则判断已经访问的无障碍位置总数,如果无障碍位置都已访问过,则说明找到可行解;如果还有无障碍位置未访问,则说明该路径不符合,应退回到上一个位置,沿其他方向继续dfs;

     当前位置不是终点,则可以沿某一方向移动,得到新位置,只有当新位置坐标未越界并且新位置不是障碍位置时,才从新位置继续进行dfs搜索;

public class UniquePaths {
	int[] dx = new int[]{-1,1,0,0};
        int[] dy = new int[]{0,0,1,-1};
        int m = 0;
	int n = 0;
	int num = 0;
	
	public int uniquePathsIII(int[][] grid) {
		m = grid.length;
		n = grid[0].length;
		//起始点坐标
        int sr=0,sc=0;
        //终点坐标
        int er=0,ec=0;
        //无障碍位置数量
        int count = 0;
        
        //寻找起始点,终点以及计算无障碍位置数量
        for(int i=0; i<grid.length; i++){
        	for(int j=0; j<grid[0].length; j++){
        		if(grid[i][j]==1){
        			sr = i; sc = j;
        		}
        		if(grid[i][j]==2){
        			er = i; ec = j;
        		}
        		if(grid[i][j]!=-1){
        			count++;
        		}
        	}
        }
       
        //记录每一个位置dfs是否已经被访问过
        boolean[][] flag = new boolean[m][n];
        //从起始点开始向四个方向进行dfs搜索
        dfs(sr, sc, grid, er, ec, count, flag);
      
		return num;  
    }
	
	private void dfs(int x, int y, int[][] grid, int er, int ec, int count, boolean[][] flag) {

		//如果已经搜索到终点,则判断是否所有无障碍位置都访问过
		//如果都访问过,则解法结果加一
		//否则回退到上一状态,沿其他方向dfs
		if(x==er && y==ec){
			if(count==1) num++;			
			else return;
		}
		
		//标记该位置,避免再次访问,并且count--
		flag[x][y]=true;
		count--;
		//从该位置开始沿四个方向进行dfs
		for(int i=0; i<4; i++){
			
			//将判断条件提前判断,避免进行递归直接返回
			//只有当移动之后坐标索引未越界,并且新位置无障碍时,才进行dfs深度搜索
			if(0<=x+dx[i] && x+dx[i]<m && 0<=y+dy[i] && y+dy[i]<n && !flag[x+dx[i]][y+dy[i]] && grid[x+dx[i]][y+dy[i]] != -1){
        		dfs(x+dx[i], y+dy[i], grid, er, ec, count, flag);
        	}
			
        }
		
		//当前位置已经搜索完毕
		//回溯状态,回到上一个位置,从上一个位置其他方向继续搜索
		count++;
		flag[x][y]=false;
	}

	public static void main(String[] args) {
		//int[][] grid = new int[][]{{1,0,0,0},{0,0,0,0},{0,0,2,-1}};
		//int[][] grid = new int[][]{{1,0,0,0},{0,0,0,0},{0,0,0,2}};
		int[][] grid = new int[][]{{0,0,0,1,-1,-1,0,-1,2,0}};
		System.out.println(new UniquePaths().uniquePathsIII(grid));
	}

}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值