递归的第三个实际案例:八皇后
老师给的思路:
//1.第一个皇后先放第一行第一列;
//2.第二个皇后放在第二行第一列、然后判断是否 OK,
//如果不 OK,则尝试放在第二列、第三列…,直到找到一个合适的位置;
//3.继续放置第三个皇后,还是第一列、第二列…,直到找到一个合适的位置;
//4.依次循环下去,直到第 8 个皇后也能放在一个不冲突的位置,就算是找到了一个正确解;
//5.当得到一个正确解时,在栈回退到上一个栈时,就会开始回溯。本次回溯之后,
//会即将第一个皇后放到第一列前提下的所有正确解全部得到;
//6.然后回头从 1 开始,第一个皇后放到第一行第二列,后面继续循环执行 2、3、4 的步骤,
//直至第一个皇后将第一行的所有列都放置过。至此,便得到了八皇后问题的所有放置解法。
我自己的理解
//创建一个一维数组,index+1表示第(index + 1)个皇后在第(index + 1)行,
//arr[index] = 3;表示这个皇后在第4列
//基本思路:假定arr[0] = 0;即第一个皇后在第一列,第二个皇后在第二行即arr[1]
//判断标准:如果:arr[0] = arr[1],那么表示两个皇后在同一列,
//如果|arr[1]-arr[0]| = |1-0|;表示两个皇后在同一斜线上
//假如arr[0] = 7,arr[1] = 6;判断斜线:|0-1| = |7-6|;这个时候就需要取绝对值,绝对值是非负数
第一步:
编写输出算法,代码:
int arr[] = new int[8];
//输出算法
public void print(){
for(int i = 0; i < arr.length; i++){
System.out.print(arr[i] + " ");
}
System.out.println();
}
第二步:
编写判断是否冲突的代码
public boolean judge(int index){
for(int i = 0; i < index; i++){//判断和之前的index个皇后是否冲突
if(arr[i] == arr[index] || Math.abs(arr[index]-arr[i]) == Math.abs(index -i)){
return false;
}
}
return true;//必须放在for循环外部,
}
放在for循环外部的原因:假如是第7个皇后,必须判断完前六个皇后都不冲突再返回true
第三步:
放置算法:即调用方法,递归
//放置算法,即在棋盘中放置第几个皇后
public void put(int index){
//首先判断index是否等于8
if(index == 8){//当index等于8的时候,即第9个棋子,已经完成了8个棋子的放置
print();//调用输出算法
}else{
for(int i = 0; i < 8; i++){
arr[index] = i;//
if(judge(index)){//如果返回true则继续判断
put(index + 1);
}
}
}
}
完整代码
public class QueenTest{
public static void main(String[] args){
T t1 = new T();
t1.put(0);
}
}
class T{
int arr[] = new int[8];
//输出算法
public void print(){
for(int i = 0; i < arr.length; i++){
System.out.print(arr[i] + " ");
}
System.out.println();
}
//判断算法
public boolean judge(int index){
for(int i = 0; i < index; i++){//判断和之前的index个皇后是否冲突
if(arr[i] == arr[index] || Math.abs(arr[index]-arr[i]) == Math.abs(index -i)){
return false;
}
}
return true;//必须放在for循环外部,
}
//放置算法,即在棋盘中放置第几个皇后
public void put(int index){
//首先判断index是否等于8
if(index == 8){//当index等于8的时候,即第9个棋子,已经完成了8个棋子的放置
print();//调用输出算法
}else{
for(int i = 0; i < 8; i++){
arr[index] = i;//
if(judge(index)){//如果返回true则继续判断
put(index + 1);
}
}
}
}
}
简单的内存分析图
统计共有多少种解法的代码
public class QueenTimes{
public static void main(String[] args){
int count = 0;
T t1 = new T();
count = t1.put(0);
System.out.println("八皇后一共有" + count + "种解法");
}
}
class T{
int arr[] = new int[8];
int count = 0;
//输出算法
public void print(){
for(int i = 0; i < arr.length; i++){
System.out.print(arr[i] + " ");
}
System.out.println();
count ++;
}
//判断算法
public boolean judge(int index){
for(int i = 0; i < index; i++){//判断和之前的index个皇后是否冲突
if(arr[i] == arr[index] || Math.abs(arr[index]-arr[i]) == Math.abs(index -i)){
return false;
}
}
return true;//必须放在for循环外部,
}
//放置算法,即在棋盘中放置第几个皇后
public int put(int index){
//首先判断index是否等于8
if(index == 8){//当index等于8的时候,即第9个棋子,已经完成了8个棋子的放置
print();//调用输出算法
}else{
for(int i = 0; i < 8; i++){
arr[index] = i;//
if(judge(index)){//如果返回true则继续判断
put(index + 1);
}
}
}
return count;
}
}