上一篇中我们讲了八皇后递归的思路,但是代码实在是不堪入目,因为从零到七要试探上千万次,简直无法忍受,而我们也知道八皇后的排列方式就是8!的全排列问题,由此可在上一篇的基础上进行代码优化进一步减少运行次数(但还不是最简方法),由原来的需要判断上千万次减少为40320次虽然还是很多,但对于计算机来说还是可以接受的。
代码以及说明如下:
import java.util.ArrayList;
import java.util.List;
public class QueenDemo {
public static void main(String[] args) {
int[] arr=new int[9];//多出一个位置存结果
List<Integer> list= new ArrayList<>();//list用来存储已有的值,防止重复,用栈的话也可以
getCount(arr,list,8);
System.out.println(arr[8]);
}
//全排列问题的解决方案8皇后运行40320次
public static void getCount(int[] arr,List<Integer> list,int max){
for (int i = 0; i < arr.length-1; i++) {
//如果list中包含之前的值就跳过,减少判断次数
if(list.contains(i)){
continue;
}
arr[max-1]=i;
//没有就添加进去
list.add(i);
//当数组调整好就去验证
if(max==1){
if(judge(arr)){
arr[arr.length-1]++;//可以把if条件取消验证全排列次数
}
//arr[arr.length-1]++;
}
else {
getCount(arr,list,--max);
//这里值得注意,如果退出最后一层循环列表中要删除两次最后一位,其余循环只删除一次
// 它喵的就在这里我debug了一个半点,固定删除一次或删除两次都有问题,只有这样才行,至于为什么,debug一下你就知道,真他喵的坑爹
if(max==1){
list.remove(list.size()-1);
list.remove(list.size()-1);
}
else {
list.remove(list.size()-1);
}
max++;//max一定要还原切记,这里也卡了我半天
}
}
}
public static boolean judge(int[] arr){
for (int i = 0; i < arr.length-1; i++) {
for (int j = arr.length-2; j >i; j--) {
if(Math.abs(i-j)==Math.abs(arr[i]-arr[j])){//传进来的数组一定不可能有相同的值,只需判断斜排就可以了
return false;
}
}
}
return true;
}
}