JAVA算法:棋盘走法、方格走法常见算法问题汇总

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/seagal890/article/details/89423055

JAVA算法:棋盘走法、方格走法常见算法问题汇总

问题一:方格从左上角走到右下角的走法数

给定一个m*n的方格,机器人只能向右走或向下走,求机器人从方格左上角走到右下角共有多少种走法。

对于2*2的方格有两种走法,3*3的方格有6种走法,求对m*n的方格有多少种走法。

算法分析

算法设计

package com.bean.algorithm.matrix;

public class CountPath {

	/*
	 * 走方格问题:从左上角走到右下角的路径数量
	 * 当只有1个格子时:可以看作m=n=1时,其实没有可走的路径,记为0;
	 * 当只有2个格子时,无论是横着放置,还是竖着放置,路径数一样的。
	 * 为什么?横着放置时,表示只能一直从左向右走;
	 * 竖着放置时,表示只能一直从上向下走。
	 * 当有4个格子时:可走的路径为2.
	 * 当有6个格子时,可走的路径为3.
	 * 找找规律。
	 */
	public static int countMatrixPath(int m, int n) {

		/*
		 * 开辟一个动态数组dp;dp数组的大小和原方格大小相同。
		 * 定义dp[i][j]表示从左上角的格子(原点或者起点)走到nums[i][j]的格子共有多少种走法。
		 * 首先分析题目的状态转移方程:因为机器人只能向右或向下走,
		 * 对于非边界的每一个格子nums[i][j],都有:dp[i][j]=dp[i-1][j]+dp[i][j-1]
		 * 然后考虑边界条件:
		 * 当i=0时,机器人只能向右走,
		 * 当j=0时,只能向下走,
		 * 所以对于边界点nums[i][j]有,
		 * 当i=0时,有dp[i][j]=dp[i][j-1];(表示当前位置是从左向右走过来的)
		 * 当j=0时,有dp[i][j]=dp[i-1][j];(表示当前位置是从上向下走过来的)
		 *  
		 * */
		int[][] dp = new int[m][n];

		for (int i = 0; i < m; i++) {
			for (int j = 0; j < n; j++) {
				
				if (i != 0 || j != 0) {// 避免i,j同时为0,数组下标越界
					if (i == 0) {//边界条件:表示从左向右走
						dp[i][j] = dp[i][j - 1];
					}
					else if (j == 0) {//边界条件:表示从上向下走
						dp[i][j] = dp[i - 1][j];
					}
					else {
						//对于非边界上的格子
						dp[i][j] = dp[i][j - 1] + dp[i - 1][j];
					}
				} else
					dp[i][j] = 1;

			}
		}
		//根据dp[i][j]的定义,其表示从左上角的格子(起点)走到nums[i][j]的格子共有多少种走法。
		//返回dp[m-1][n-1]的值。
		return dp[m - 1][n - 1];

	}

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		int M = 4;
		int N = 3;

		int numbersofPath = countMatrixPath(M, N);
		System.out.println("Numbers of Path is: " + numbersofPath);

	}

}

输出运行结果:

Numbers of Path is: 10

问题二:方格中的值表示某种意义,从左上角走到右下角时求最大值或者最小值的路径

例如:给定一个矩阵m,从左上角开始每次只能向右或者向下走,最后到达右下角的位置,路径上所有的数字累加起来就是路径和,返回所有的路径中最小的路径和。

算法分析

算法设计

package com.bean.algorithmexec;

/*
 * https://blog.csdn.net/seagal890/article/details/88603064
 * */
public class MatrixPath {
	/*
	 * 给定一个矩阵m,从左上角开始每次只能向右或者向下走,最后到达右下角的位置,
	 * 路径上所有的数字累加起来就是路径和,返回所有的路径中最小的路径和。
	 * 例如:
	 * 1 3 5 9 
	 * 8 1 3 4 
	 * 5 0 6 1
	 * 8 8 4 0
	 * 路径 1,3,1, 0,6,1,0 是所有路径中路径和最小的,所以返回12。
	 * */

	/*
	 * 计算方法
	 * */
	
	public static int minPathSum(int [][] m) {
		
		if(m==null || m.length==0 || m[0]==null || m[0].length ==0) {
			return 0;
		}
		
		int row=m.length;
		int col=m[0].length;
		int[][] dp=new int[row][col];
		dp[0][0] = m[0][0];
		
		for(int i=1;i<row;i++) {
			dp[i][0] = dp[i-1][0]+m[i][0];
		}
		
		for(int j=1;j<col;j++) {
			dp[0][j] = dp[0][j-1]+m[0][j];
		}
		
		for(int i=1;i<row;i++) {
			for(int j=1;j<col;j++) {
				dp[i][j] = Math.min(dp[i-1][j], dp[i][j-1])+m[i][j];
			}
		}
				
		return dp[row-1][col-1];
	}
	
	
	/*
	 * 创建一个 M*N的矩阵,并赋予行和列随机整数值,元素的取值范围在1-10之间。
	 * */
	
	public static int[][] createMatrix(int m, int n) {
		
		int [][] matrix=new int[m][n];
		int seed=0;
		for(int i=0;i<m;i++) {
			for(int j=0;j<n;j++) {
				seed=(int) ((Math.random()*10)+1);
				matrix[i][j]=seed;
			}
		}
		
		return matrix;
	}
	
	
	/*
	 * 输出矩阵 
	 * */
	public static void printMatrix(int[][] matrix) {
		for(int i=0;i<matrix.length;i++) {
			for(int j=0;j<matrix[0].length;j++) {
				System.out.print(matrix[i][j]+"\t");
			}
			System.out.println();
		}
	}
	
	public static void main(String[] args) {
		// TODO Auto-generated method stub

		int[][] matrix=createMatrix(4,4);
		printMatrix(matrix);
		
		int sum=minPathSum(matrix);
		
		System.out.println("sum = "+sum);
		
	}

}

输出运行结果:(矩阵值是随机生成的)

7    2    8    3    
10    3    8    3    
4    9    5    3    
8    10    4    8    
sum = 34

问题三 LeetCode 62. Unique Paths

Unique Paths 原题链接:https://leetcode.com/problems/unique-paths/description/
Unique Paths II 原题链接:https://leetcode.com/problems/unique-paths-ii/description/
62. 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?

参考博文:https://blog.csdn.net/seagal890/article/details/79781703 解决

问题四 LeetCode 63. Unique Paths II 

类似的问题是,行进路径上设置了一些障碍,而障碍是不可走的。

63. Unique Paths II
Follow up for “Unique Paths”:

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.

For example, 
There is one obstacle in the middle of a 3x3 grid as illustrated below.


[0,0,0], 
[0,1,0], 
[0,0,0] 

The total number of unique paths is 2.

Note: m and n will be at most 100.

63题和62题类似,不同的是设置了 obstacle,当遇到obstacle时,此路不同。 
解题思路仍然是使用DP动态规划算法。无非对于dp数组元素,在obstacle位置将器值置位0即可。 
需要增加一些判断条件。

算法设计

当遇到障碍时:dp[i][j] = 0;

当不是障碍时:dp[i][j] = dp[i - 1][j] + dp[i][j - 1];

public static int uniquePathsWithObstacles(int[][] obstacleGrid) {
        //获取被处理数组的维度,m行n列
        int m = obstacleGrid.length;
        int n = obstacleGrid[0].length;
        if(m==0 || n==0) return 0; 
        //计算时间,即如果左上角的元素值为1,直接返回0。
        if(obstacleGrid[0][0]==1) return 0;

        //DP(Dynamic Programming)数组为s,s与被处理的二维数组具有相同的行和列数
        int[][] dp = new int[m][n];
        //用dp[i][j]表示路径数
        //当方格的左上角和右下角(第一个元素值为1时和最后一个元素值为1时,路径都为0)
        dp[0][0] = obstacleGrid[0][0] == 0 ? 1 : 0;
        if (dp[0][0] == 0)
            return 0;
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                if (obstacleGrid[i][j] == 1)
                    //如果是路障,则dp[i][j]=0
                    dp[i][j] = 0;
                else if (i == 0) {
                    if (j > 0)
                        dp[i][j] = dp[i][j - 1];
                } else if (j == 0) {
                    if (i > 0)
                        dp[i][j] = dp[i - 1][j];
                } else
                    //如果不是路障,则状态方程为dp[i][j] = dp[i - 1][j] + dp[i][j - 1]
                    dp[i][j] = dp[i - 1][j] + dp[i][j - 1];
            }
        }
        return dp[m - 1][n - 1];
    }

问题五 马走8×8棋盘问题

参考博文:https://blog.csdn.net/seagal890/article/details/79339757

经典问题:给定一个8×8棋盘,马从任意位置开始,走“日”字,不重复的走完棋盘上的所有位置。

如图所示:

假设从坐标为(2,2)的点开始走,有8个方向可以选择。所以每次都要依据这最多8个方向进行选择。 
贪心算法不是对所有问题都能得到整体最优解,关键是贪心策略的选择,选择的贪心策略必须具备无后效性,即某个状态以前的过程不会影响以后的状态,只与当前状态有关。在处理马踏棋盘问题时,每次在至多8个可选的方向中,首先通过验证其中一个方向可以成功。贪心算法同样是试探至多的八个可能的出口,但是八个出口的排序并非按照前述的顺时针,而是按照每个可能出口的进一步出口数的递增排序,所以每次先试探的总是进一步出口较少的出口,能够给之后的出口更多的选择,因此贪心算法是比较高效的,而且它不回溯。

猜你喜欢

转载自blog.csdn.net/seagal890/article/details/89423055