n后问题:在n*n的×××上放置n个皇后,按照国际象棋的规则,使其彼此不攻击。即每两个皇后之间不处于同一行、同一列、同一对角线。
首先,行不同可以理解为第i个皇后必须在第i行,体现在算法中就是当第i个皇后确定位置后,第i+1个皇后必须在第i+1行寻找满足条件的位置。其次,为满足列不同,需要在第i个皇后选择位置时,判断位置的行j,是否在之前所有i-1个皇后中没有相同的行。最后,关于对角线的判断可以使用对角线的满足条件i-j=a-b或i+j=a+b来判断,即要求当前要判断的位置的行列和差都与之前已确定位置的皇后的行列和差不同。同时满足上述三个条件才表示第i个皇后的位置是满足要求的,如果第i个皇后在第i行无法获得满足条件的位置,则表示当前i-1个皇后的位置已不会是有效解,在回溯法的解空间树中,可以剪去该结点,无需遍历该结点的子结点树,应当进行回溯。
package test; import java.util.HashMap; import java.util.Map; /** * Created by saishangmingzhu on 2018/12/15. */ public class EightQueens { public static void main(String[] arg){ new EightQueens().backtracking(); } int n=8; int m=8; int count=0; /** * 回溯法 */ private void backtracking(){ int queeni=0; int i=0; int j=0; for (;j<m;j++) { int[][] chessboard=new int[m][m]; //因为每行只有一个皇后,所有可以使用Map中的key存储行,value存储列 Map<Integer,Integer> queenMap=new HashMap<>(); chessMoves(queeni, i, j, chessboard,queenMap); System.out.println(); } } private void chessMoves(int queeni,int i,int j,int[][] chessboard,Map<Integer,Integer> queenMap){ if (!(judgeRow(i, j,queenMap) == 0 && judgeDiagonal(i, j, queenMap) == 0 )) return ; chessboard[i][j] = 1;//queeni皇后的位置 queenMap.put(i,j); if (queeni + 1<n) { for (int k = 0; k < m; k++) { chessMoves(queeni + 1, i + 1, k, chessboard,queenMap); } } else { print(chessboard); } chessboard[i][j] = 0; queenMap.remove(i); } private void print(int[][] chessboard){ System.out.println("==="+(++count)+"===="); for (int i=0;i<m;i++){ for (int j=0;j<m;j++){ System.out.print(chessboard[i][j]); } System.out.println(); } } /** * 判断列 * @param i * @param j * @param queenMap * @return */ private int judgeRow(int i,int j,Map<Integer,Integer> queenMap){ for (Integer value:queenMap.values()){ if (value==j){ return 1; } } return 0; } /** * 判断对角线 * @param i * @param j * @param queenMap * @return */ private int judgeDiagonal(int i,int j,Map<Integer,Integer> queenMap){ for (Integer key:queenMap.keySet()){ int value=queenMap.get(key); if (key-value==i-j || key+value==i+j){ return 1; } } return 0; } }