一、基本思想是用元素进入链表的先后表明行号,具体数值表明列号,注释很清楚了就不再说明,直接贴代码了
import java.util.ArrayList;
public class EightQueen {
/**
* 判断下一个皇后在当前状态下时候可放
* */
public boolean YesNo(ArrayList<Integer> state,int nextX) {
int nextY = state.size(); //存放已经放了几行
int absX; //横向差值绝对值
for(int i=0;i<nextY;i++) { //测试当前皇后与之前的是否冲突
absX = Math.abs(nextX - state.get(i)); //计算横向距离
if(absX==0 || absX == (nextY - i)) //absX=0表明在同一列上,absX=(nextY - i)表明在斜线上,只要一个相等返回错误
return false;
}
return true; //若未返回错误则新位置可放皇后,返回正确
}
/**
* 主要方法,用来递归解决八皇后
* */
public void Queen(ArrayList<Integer> state,int num) {
for(int i=0;i<num;i++) { //遍历寻找可以放的地点
if(YesNo(state, i)) { //判断i点时候和以往皇后是否冲突
state.add(i); //不冲突把新的皇后位置添加到链表
System.out.println(state);
if(state.size() == num) { //添加后如果皇后数量时候已满
System.out.println(state); //皇后满了输出皇后位置
state.remove(state.size()-1); //由于最后一个没有进入递归所以方法最后的移除不生效,会导致少移除一个,这里需要补上这句移除一个皇后
}else Queen(state, num); //皇后不满则直接添加然后递归新的状态
}
}
if(state.size()>=1)
state.remove(state.size()-1); //如果遍历所有位置都不能放置则移除一个皇后
}
public static void main(String[] args) {
long start=System.currentTimeMillis(); //获取程序开始时间
int num = 8; //皇后数量,可任意写
ArrayList<Integer> state = new ArrayList<>();
new EightQueen().Queen(state, num); //要测的程序
long end=System.currentTimeMillis(); //获取程序结束时间
System.out.println("程序运行时间: "+(end-start)+"ms");
}
}
二、如果对Queen函数中第一个state.remove(state.size()-1);想不明白的话也可以替换成下面的Queen函数,仅仅替换Queen函数其他不变即可
public void Queen(ArrayList<Integer> state,int num) {
for(int i=0;i<num;i++) { //遍历寻找可以放的地点
if(YesNo(state, i)) { //判断i点时候和以往皇后是否冲突
if(state.size() == num-1) { //添加后如果皇后数量时候已满
for(int j=0;j<state.size();j++) //下面三行是皇后满了输出皇后位置
System.out.print(state.get(j)+", ");
System.out.println(i);
}else {
state.add(i); //不冲突把新的皇后位置添加到链表
Queen(state, num); //皇后不满则直接添加然后递归新的状态
}
}
}
if(state.size()>=1)
state.remove(state.size()-1); //如果遍历所有位置都不能放置则移除一个皇后,回到上一层
}