八皇后问题,是一个古老而著名的问题,是回溯算法的典型案例。该问题是国际西洋棋棋手马克斯·贝瑟尔于1848年提出:在8×8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。
1.方案1:用二维数组表示棋盘,回溯搜索
/**
 * 回溯,深度优先搜索,递归
 * @author LENOVO
 *
 */
public class 八皇后问题 {
	public static boolean visit[][]=new boolean[8][8];//标记棋盘数组
	public static int c=0;//记录答案
	public static void main(String[] args) {//主函数
		dfs(0);
		System.out.println("答案:"+c);
	}
	public static void dfs(int y) {//y表示放第y个皇后,dfs搜索
		if(y>=8) {//如果八个皇后已放满
			c++;
			System.out.println("--------------------------第"+c+"个答案----------------------");
			System.out.println();
			for(int i=0;i<8;i++) {
				for(int j=0;j<8;j++) {
					System.out.print((visit[i][j]?"1":"0")+"\t");
				}
				System.out.println();
			}
			return;
		}
		for(int i=0;i<=7;i++) {//循环遍历8列
		        //可以放否,可以,继续递归搜索,否则回归
			if(hang(i)&&lie(y)&&xiangxian1(i,y)&&xiangxian4(i,y)) {
				visit[i][y]=true;
				dfs(y+1);
				visit[i][y]=false;
			}
		}
	}
	public static boolean hang(int x) {//判断行
		for(int i=0;i<8;i++) {
			if(visit[x][i]) {
				return false;
			}
		}
		return true;
	}
	public static boolean lie(int y) {//判断列
		for(int i=0;i<8;i++) {
			if(visit[i][y]) {
				return false;
			}
		}
		return true;
	}
	public static boolean xiangxian1(int x,int y) {//    \ 二四象限
		if(x>y) {
			x=x-y;y=0;
		}else if(x<y) {
			y=y-x;x=0;
		}else {
			x=0;y=0;
		}
		for(;x<8&&y<8;) {
			if(visit[x++][y++]) {
				return false;
			}
		}
		return true;
	}
	public static boolean xiangxian4(int x,int y) {//   / 一三象限
		int i=x,j=y;
		while(i<8&&j>=0) {
			if(visit[i++][j--]) {
				return false;
			}
		}
		while(x>0&&y<8) {
			if(visit[x--][y++]) {
				return false;
			}
		}
		return true;
	}
}
2.方案2,用一维数组代表二维数组的棋盘,一维数组的下表代表行,一维数组的值代表列,然后回溯搜索
public class Queen {	
	static int chessboard[];
	static int count=0;
	public static void main(String[] args) {
		chessboard =new int[]{-1,-1,-1,-1,-1,-1,-1,-1,-1};
		change(1);
		System.out.println(count);
	}
	public static boolean judge(int pointi,int pointj){//判断某个皇后是否与已有皇后冲突
		System.out.println(pointi+"  "+pointj);
	    for(int i=1;i<pointi;i++){
	    	System.out.println("    "+(pointi-i)+":"+(pointj-chessboard[i]));
	        if(pointj==chessboard[i])return false;//同一列
	        if((pointi-i)==(pointj-chessboard[i]))return false;//同一主对角线
	        if((pointi-i)+(pointj-chessboard[i])==0)return false;//同一副对角线
	    }
	    return true;
	}
	public static void change(int row){//在第row行找能放皇后的位置
	    for(int i=1;i<9;i++){//从1~8遍历这一行的八个空位
	        if(judge(row,i)){ //如果可以放这个位置就记录下第row个皇后的位置
	            chessboard[row]=i;
	            if(row==8){//如果八个皇后都放满了统计一下
	                count++;
	                return;
	            }
	            change(row+1);//还有皇后没放递归放下一个皇后
	        }
	    }
	    chessboard[--row]=-1;//如果这一行没有可放的位置说明上一行皇后放的位置不行,
	                        //要为上一个皇后寻找新的可放位置
	    return;
	}
}