数据结构和算法(递归概念、迷宫回溯问题和八皇后问题代码实现)

递归的概念:

在这里插入图片描述
在这里插入图片描述

递归能够做解决什么问题?

在这里插入图片描述

使用递归时需要注意的问题:

在这里插入图片描述

递归的第一个应用:迷宫回溯问题

迷宫模拟:

定义一个8×7的数组模拟迷宫:
1表示围墙,0表示可以走的路
图中左上红圈为起点,右下红圈为终点
利用代码找到从起点到终点的路径
在这里插入图片描述

使用递归回溯找寻路

说明
1.定义map 表示地图
2.定义i,j,表示从地图的哪个位置开始出发
3.如果能到map[6][5]位置,则说明通路找到
4.约定:当map[i][j] 为 0 表示该点没有走过,当为1表示墙,2表示通路可以走,3表示该点已经走过,但是走不通
5.在走迷宫时,需要确定一个策略(方法)下 -> 右 -> 上 -> 左,如果该点走不通,则开始回溯

	/**
	 * 
	 * @param map 表示地图
	 * @param i 从哪个位置开始找
	 * @param j
	 * @return 如果找到位置,就返回true,否则返回false
	 */
	public static boolean setWay(int[][] map, int i, int j) {
		if (map[6][5] == 2) {// 终点,通道已找到,不再自我调用,开始回溯
			return true;
		} else {
			if (map[i][j] == 0) {// 如果当前这个点没有走过
				// 按照策略 下、右、上、左
				map[i][j] = 2;// 假定该点是可以走通的
				if (setWay(map, i + 1, j)) {//向下走
					return true;
				} else if (setWay(map, i, j + 1)) {//向右走
					return true;
				} else if (setWay(map, i - 1, j)) {//向上
					return true;
				} else if (setWay(map, i, j-1)) {//向左走
					return true;
				}else {
					//如果上述通路都不能走通,则表示是死路,不再自我调用,开始回溯
					map[i][j] = 3;
					return false;
				}

			}else {
				//如果该点不为0,为1、2、3,就返回false,(为什么有2:如果从2继续找路,可能会进入死循环)
				//不再自我调用,开始回溯
				return false;
			}
		}
	}

递归的第二个应用:八皇后问题

八皇后问题介绍
八皇后问题,是一个古老而著名的问题,是回溯算法的典型案例。该问题是国际西洋棋棋手马克斯·贝瑟尔于1848年提出:在8×8格的国际象棋上摆放八个皇后,使其不能互相攻击,即:任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。(92种)

思路分析:

在这里插入图片描述
在这里插入图片描述

使用递归解决八皇后问题的完整代码(可直接复制运行):
public class Queen8 {
	// 定义一个max表示共有多少个皇后
	int max = 8;
	// 定义数组array,保存皇后放置位置的结果,比如arr = {0,4,7,5,2,6,1,3}
	int[] array = new int[max];
	static int count = 0;//用来计数

	public static void main(String[] args) {
		Queen8 queen8 = new Queen8();
		queen8.check(0);
		System.out.printf("一共有%d种解法",count);
		
	}

	// 核心方法
	// 查看当我们放置 第 n 个皇后、就去检测该皇后是否和前面已经摆放的皇后冲突
	// 使用递归,每一次递归都有一个for循环,因此会有回溯
	private void check(int n) {
		if (n == max) {// n = 8,其实已经放好皇后了,因为从0开始
			print();// 开始回溯的起点,直接打印
			return;
		}
		for (int i = 0; i < max; i++) {
			//先把当前这个皇后 n ,放到该行的第 1 列
			array[n] = i;
			//判断当放置第 n 个皇后到 i 列,是否冲突
			if(judg(n)) {//不冲突
				//接着开始放n+1个皇后,即开始递归
				check(n+1);
			}
			//如果有冲突,不要紧,进入循环
		}
	}

	/**
	 * 
	 * @param n 表示第 n 个皇后
	 * @return
	 */
	private boolean judg(int n) {
		for (int i = 0; i < n; i++) {
			// 下标表示行,值表示列
			// array[i] == array[n] -> 值相等 -> 列相等
			// Math.abs(i-n)->下标之差-> 行之间的差距
			// Math.abs(array[i]-array[n])->值之间的差->列之间的差距
			// Math.abs(i-n) == Math.abs(array[i]-array[n]) ->
			// 行之间的差距和列之间的差距相等,构成等腰直角三角形,即在斜线上

			if (array[i] == array[n] || Math.abs(i - n) == Math.abs(array[i] - array[n]))
				return false;
		}
		return true;
	}

	// 将结果输出
	private void print() {
		count++;
		for (int i = 0; i < array.length; i++) {
			System.out.print(array[i] + " ");
		}
		System.out.println();
	}
}

发布了68 篇原创文章 · 获赞 12 · 访问量 5199

猜你喜欢

转载自blog.csdn.net/qq_40963076/article/details/105148786