递归需要遵守的重要规则
- 执行一个方法,就创建一个新的受保护的独立空间(栈空间)
- 方法的局部变量是独立的,不会相互影响,比如n变量
- 如果方法中使用了引用类型变量(比如数组),就会共享该引用类型的数据
- 递归必须向退出递归条件逼近,否则就是无限递归,会栈溢出
- 当一个方法执行完毕,遇到return就会返回,结果返回给调用者
小球走迷宫(回溯算法)
代码实现
我们先绘制出地图
int[][] map = new int[8][7];
//上下置为1
for (int i = 0;i<7;i++){
map[0][i] =1 ;
map[7][i]=1;
}
//左右全部置为1
for (int i=0;i<8;i++){
map[i][0]=1;
map[i][6]=1;
}
//设置挡板
map[3][1]=1;
map[3][2]=1;
//输出地图
System.out.println("地图的情况");
for (int i=0;i<8;i++){
for (int j=0;j<7;j++){
System.out.print(map[i][j]+" ");
}
System.out.println();
}
完成递归找路的方法
- map表示地图
- i,j 表示从地图哪个位置开始出发(1,1)
- 如果小球能到map[6][5]位置,说明通路
- 约定:当map[i][j]为0表示该点没有走过,1为墙,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{
return false;
}
}
}
八皇后问题(回溯算法)
算法思路分析
- 将第一个皇后放在第一行第一列
- 第二个皇后放在第二行第一列,然后判断是否ok,如果不行继续放第二列,第三列...依次放完所有列,找到一个合适
- 继续第三个皇后,还是继续第一列、第二列....直到第8个皇后也能放在一个不冲突的位置,算找到一个正确解
- 当得到一个正确解,在栈回退到上一个栈时,就会开始回溯,即将第一个皇后,放在第一列的所有正确解,全部得到
- 然后回头继续第一个皇后放第二列,继续重复上面操作。
说明:理论上我们应该用二维数组表示棋盘,实际上我们可以通过一维数组来解决
数组的下标表示第几行(第几个皇后),值表示第几列。注意是从0开始
代码实现
public class Queue8 {
int max=8;//保存皇后个数
int[] array = new int[max];
static int count = 0;
public static void main(String[] args) {
Queue8 queue8 = new Queue8();
queue8.check(0);
System.out.println("一共有"+count+"种解法");
}
//放置第n个皇后
private void check(int n){
if (n == max) { // n=8已经放第九个了 已经放好了说明
print();
return;
}
//依次放入皇后并判断是否冲突
for (int i=0;i<max;i++){
//先把当前皇后n 放到第1列 不行再慢慢往后a
array[n]=i;
if (judge(n)){
check(n+1);
}
}
}
//当我们放第n个皇后时,看是不是跟前面冲突
//n表示放第n个皇后
private boolean judge(int n){
for (int i = 0 ; i < n ; i++){
//判断是否在同一行
//或者判断是否同一斜线Math.abs(n-i)==Math.abs(array[n]-array[i]
//如果同一斜线他们的横坐标差绝对值应该等于纵坐标差绝对值
if (array[i]==array[n] || Math.abs(n-i)==Math.abs(array[n]-array[i])){
return false;
}
}
return true;
}
//写一个方法可以将最后结果打印
private void print(){
count++;
for (int i=0;i<array.length;i++){
System.out.print(array[i]+" ");
}
System.out.println();
}
}