递归的基本规则
- 递归中的方法的局部变量都是独立的
- 如果方法的形参是引用类型, 由于传递的是指针递归方法之间是共享的
- 递归必须向退出的条件逼近, 否则就是无限递归
迷宫问题
- map[i][j]: 0表示未走过, 可以尝试; 1表示墙; 2表示该路, 可以走通; 3表示该路, 已走过, 但走不通
- 当 map[6][5] == 2, 则已到达目的地(最右下角), 结束递归
public class MazeApp {
public static void main(String[] args) {
/** 通过二维数组, 模拟8行7列的迷宫地图*/
int horizontalNum = 8;
int verticalNum = 7;
int[][] map = new int[horizontalNum][verticalNum];
/** 第1行和8行, 使用1填墙*/
for (int v = 0; v < verticalNum; v++) {
/** 从1(0)列开始, 横向只将给1-8(0-7)行填1*/
map[0][v] = 1;
map[7][v] = 1;
}
/** 第1列和7行, 使用1填墙*/
for (int h = 1; h < horizontalNum - 1; h++) {
/** 从2(1)行开始到7行(6), 循环只给每行首元素(0)和尾元素(6)填1*/
map[h][0] = 1;
map[h][6] = 1;
}
/** 内部设置挡板*/
map[3][1] = 1;
map[3][2] = 1;
// map[1][2] = 1;
// map[2][2] = 1;
/** 打印地图*/
System.out.println("地图:");
for (int h = 0; h < horizontalNum; h++) {
for (int v = 0; v < verticalNum; v++) {
System.out.print(map[h][v] + " ");
}
System.out.println();
}
/** 策略1: 从第2行&第2列开始起步*/
setStrategy1(map, 1, 1);
/** 策略2*/
//setStrategy2(map, 1, 1);
System.out.println("走过的路线:");
for (int h = 0; h < horizontalNum; h++) {
for (int v = 0; v < verticalNum; v++) {
System.out.print(map[h][v] + " ");
}
System.out.println();
}
}
/** 尝试方向策略: 下->右->上->左*/
public static boolean setStrategy1(int[][] map, int h, int v) {
/** 已到达目的地(最右下角), 结束递归*/
if(map[6][5] == 2) {
return true;
} else {
/** 0表示未走过, 可以尝试*/
if(map[h][v] == 0) {
/** 假定当前点是可以走通*/
map[h][v] = 2;
if(setStrategy1(map, h + 1, v)) { /** 向下走*/
return true;
} else if (setStrategy1(map, h, v + 1)) { /** 向右走*/
return true;
} else if (setStrategy1(map, h - 1, v)) { /** 向上走*/
return true;
} else if (setStrategy1(map, h, v - 1)){ /** 向左走*/
return true;
} else { /** 已走过, 但走不通的点*/
map[h][v] = 3;
return false;
}
} else {
return false;
}
}
}
/** 尝试方向策略: 上->右->下->左*/
public static boolean setStrategy2(int[][] map, int h, int v) {
/** 已到达目的地(最右下角), 结束递归*/
if(map[6][5] == 2) {
return true;
} else {
/** 0表示未走过, 可以尝试*/
if(map[h][v] == 0) {
/** 假定当前点是可以走通*/
map[h][v] = 2;
if(setStrategy2(map, h - 1, v)) { /** 向上走*/
return true;
} else if (setStrategy2(map, h, v + 1)) { /** 向右走*/
return true;
} else if (setStrategy2(map, h + 1, v)) { /** 向下走*/
return true;
} else if (setStrategy2(map, h, v - 1)){ /** 向左走*/
return true;
} else { /** 已走过, 但走不通的点*/
map[h][v] = 3;
return false;
}
} else {
return false;
}
}
}
}
> 地图:
> 1 1 1 1 1 1 1
> 1 0 0 0 0 0 1
> 1 0 0 0 0 0 1
> 1 1 1 0 0 0 1
> 1 0 0 0 0 0 1
> 1 0 0 0 0 0 1
> 1 0 0 0 0 0 1
> 1 1 1 1 1 1 1
> 走过的路线(策略1):
> 1 1 1 1 1 1 1
> 1 2 0 0 0 0 1
> 1 2 2 2 0 0 1
> 1 1 1 2 0 0 1
> 1 0 0 2 0 0 1
> 1 0 0 2 0 0 1
> 1 0 0 2 2 2 1
> 1 1 1 1 1 1 1
> 走过的路线(策略2):
> 1 1 1 1 1 1 1
> 1 2 2 2 2 2 1
> 1 0 0 0 0 2 1
> 1 1 1 0 0 2 1
> 1 0 0 0 0 2 1
> 1 0 0 0 0 2 1
> 1 0 0 0 0 2 1
> 1 1 1 1 1 1 1
# 当内部设置挡板
map[3][1] = 1;
map[3][2] = 1;
map[1][2] = 1;
map[2][2] = 1;
## 执行过程(回溯):
* 1. (1, 1)
* 2. (2, 1) return true;
1 1 1 1 1 1 1
1 2 1 0 0 0 1
1 2 1 0 0 0 1
1 1 1 0 0 0 1
1 0 0 0 0 0 1
1 0 0 0 0 0 1
1 0 0 0 0 0 1
1 1 1 1 1 1 1
* 3. (3, 1) return false; map[3][1] != 0
* 4. (2, 2) return false; map[2][2] != 0
* 5. (1, 1) return false; map[1][1] != 0
* 6. (2, 0) return false; map[2][0] = 3
1 1 1 1 1 1 1
1 2 1 0 0 0 1
1 3 1 0 0 0 1
1 1 1 0 0 0 1
1 0 0 0 0 0 1
1 0 0 0 0 0 1
1 0 0 0 0 0 1
1 1 1 1 1 1 1
* 7. (1, 2) return false; map[1][2] != 0
* 8. (0, 1) return false; map[0][1] != 0
* 9. (1, 0) return false; map[1][0] = 3
* 最后输出:
1 1 1 1 1 1 1
1 3 1 0 0 0 1
1 3 1 0 0 0 1
1 1 1 0 0 0 1
1 0 0 0 0 0 1
1 0 0 0 0 0 1
1 0 0 0 0 0 1
1 1 1 1 1 1 1
八皇后问题
public class EightQueensApp {
/** 定义皇后数*/
static int max = 8;
static int[] queens = new int[max];
/** 解决方式的总数*/
static int count = 0;
/** 判断冲突的总数*/
static int conflictedCount = 0;
public static void main(String[] args) {
setPosition(0);
System.out.println("解决方式的总数为 " + count);
System.out.println("判断冲突的总数为 " + conflictedCount);
}
/**
* 1) num是第 num个皇后(第几行的皇后)
* 2) 经过 for(int pos = 0; pos < max; pos++)依次放好8皇后
* 3) 循环递归调用 setPosition(num + 1), 直到8位皇后放好完成了一个解决方式后打印
* */
private static void setPosition(int num) {
/** 8位皇后已放好, 完成了一个解决方式*/
if(num == max) {
print();
return;
}
/** 循环依次放好8皇后*/
for(int pos = 0; pos < max; pos++) {
/** 第 num的皇后放到 pos位置上后*/
queens[num] = pos;
/** 放好第 num皇后到 pos位置后, 判断是否冲突*/
if(judge(num)) {
/** 如果不冲突, 接着放下一个皇后*/
setPosition(num + 1);
}
/** 如果冲突, 就会将第 num的皇后, 向右移一位 array[num] = pos, 再继续判断*/
}
}
/** 判断规则: 棋盘上放置8个棋子(皇后), 且相互不冲突(皇后在同一行, 同一列和同一斜线上都属冲突)*/
private static boolean judge(int num) {
conflictedCount++;
for(int pos = 0; pos < num; pos++) {
/**
* 1) queens[num] == queens[pos]判断第 num个的皇后是否与 pos位置的皇后在同一个列上?
* 2) Math.abs(num - pos) == Math.abs(queens[num] - queens[pos])判断第 num个的皇后是否与 pos位置的皇后在同一个斜线上?
* 3) 无需判断行, 因为 num每次都在递增的
* */
if(queens[num] == queens[pos] ||
Math.abs(num - pos) == Math.abs(queens[num] - queens[pos])) {
return false;
}
}
return true;
}
/** 打印解决方式(每次打印一种)*/
private static void print() {
count++;
for (int i = 0; i < queens.length; i++) {
System.out.print(queens[i] + " ");
}
System.out.println("第 " + count + "次");
}
}
输出:
> 0 4 7 5 2 6 1 3 第 1次
> 0 5 7 2 6 3 1 4 第 2次
> 0 6 3 5 7 1 4 2 第 3次
> 0 6 4 7 1 3 5 2 第 4次
> 1 3 5 7 2 0 6 4 第 5次
> 1 4 6 0 2 7 5 3 第 6次
> 1 4 6 3 0 7 5 2 第 7次
...
...
> 解决方式的总数为 92
> 判断冲突的总数为 15720
如果您觉得有帮助,欢迎点赞哦 ~ 谢谢!!