递归调用机制原理图:
迷宫问题:
package dk.hello;
public class MiGong {
public static void main(String[] args) {
// TODO Auto-generated method stub
//先创建二维数组模拟迷宫
int[][] map = new int[8][7];
//用1表示墙,上下置为1
for (int i = 0; i < 7 ; i++) {
map[0][i] = 1;
map[7][i] = 1;
}
//左右置为1
for (int i = 0; i < map.length; i++) {
map[i][0] = 1;
map[i][6] = 1;
}
//设置挡板为1
map[3][1] = 1;
map[3][2] = 1;
//递归调用图
setWay(map,1,1);
//输出地图
System.out.println("地图");
for (int i = 0; i < map.length; i++) {
for (int j = 0; j < map[i].length; j++) {
System.out.print(map[i][j] + "\t");
}
System.out.println();
}
}
//使用递归回溯找路
//i,j表示从哪个位置开始找
//如果小球能到[6][5]就找到通路
//当map[i][j]为0表示该点没走过,1表示墙,2表示可以走,3表示该位置走过但没走通
//走迷宫策略:确定先走下面,走不通再走右面,走不通再走上面,走不通走左面,如果走不通再回溯
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 { //如果map[i][j] != 0,可能是1,2,3
return false;
}
}
}
}
//输出:
地图
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
八皇后问题:
在8×8棋盘上,有两个棋子,不能在同一行,同一列,同一斜线。有多少种摆法?
可以用一维数组表示上图摆法:arr[8] = {0,4,7,5,2,6,1,3}
- arr下标表示第几行
- arr的值表示列数
package dk.hello;
public class Queen8 {
//定义一个max表示皇后数目
int max = 8;
//定义一个数组array,保存皇后放置位置的结果arr[8] = {0,4,7,5,2,6,1,3}
int[] arr = new int[max];
static int count = 0; //统计解法数目,必须是静态变量,否则主方法是静态方法不能调用
public static void main(String[] args) {
// TODO Auto-generated method stub
new Queen8().check(0);
System.out.println(count);
}
//编写放置第n个皇后
//特别注意:check是每一次递归时都有一套for循环,因此会回溯
private void check(int n) {
if (n == max) { //n=8,前八个已经放好
print(); //直接输出
return;
}
//依次放入皇后,并判断是否冲突
for (int i = 0; i < max; i++) {
//先把当前皇后n放到该行的第1列
arr[n] = i;
//判断放置第n个皇后到i列时是否冲突
if (judge(n)) { //不冲突
//接着放第n+1个皇后
check(n+1);
}
//如果冲突,就继续执行arr[n] = i;即将第n个皇后放置在本行的后一列
}
}
//查看放置第n个皇后,是否和前面已经摆放的是否冲突
private boolean judge(int n) { //n表示第n个皇后是否和前面第i个皇后冲突
for (int i = 0; i < n; i++) {
//表示在同一列或者同一斜线(横坐标之差与纵坐标的差绝对值是否相等)
//不用判断是否在同一行
if (arr[i] == arr[n] || Math.abs(n-i) == Math.abs(arr[n]-arr[i])) {
return false;
}
}
return true;
}
//写一个方法,将皇后摆放的位置输出
private void print() {
count++;
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i]);
}
System.out.println();
}
}
//输出92种解法