N皇后的规则:任意两个皇后不在同一行,不在同一列,不在同一斜线上。
算法分析:这种问题就用回溯法。深度搜索然后回溯。用一个数组记录每一行皇后的位置,下标代表行,值代表列。对行深度搜索。
public class NQueens { public List<List<String>> solveNQueens(int n) { List<List<String>> res = new ArrayList<>(); if(n <= 0) { return res; } int[] columnVal = new int[n]; DFS_helper(n, res, 0, columnVal); return res; } public void DFS_helper(int queensNum, List<List<String>> res, int row, int[] columnVal) { if(row == queensNum)//已经遍历所有行了,得到结果 { List<String> list = new ArrayList<>(); for(int i = 0; i < queensNum; i ++) { StringBuffer sb = new StringBuffer(); for(int j = 0; j < queensNum; j ++) { if(j == columnVal[i]) { sb.append("Q"); } else { sb.append("."); } } list.add(sb.toString()); } res.add(list); } else { for(int i = 0; i < queensNum; i ++) { columnVal[row] = i; if(isValid(row, columnVal))//合法,就寻找下一行的位置,否则,变换当前行的值 { DFS_helper(queensNum, res, row+1, columnVal); } } } } public boolean isValid(int row, int[] columnVal) { for(int i = 0; i < row; i ++) { if(columnVal[i] == columnVal[row] || Math.abs(columnVal[row] - columnVal[i])== row - i) { return false; } } return true; } public static void main(String[] args) { NQueens q = new NQueens(); List<List<String>> list = q.solveNQueens(8); Iterator<List<String>> it = list.iterator(); int count = 0; while(it.hasNext()) { System.out.println(it.next()); count ++; } System.out.println(count); } }
NQueens2:计算有多少种解决方案。
算法分析:用一个成员变量来记录解决方案的个数。
public class Nqueens2 { public int count; public int totalNQueens(int n) { count = 0; if(n <= 0) { return count; } int[] columnVal = new int[n]; DFS_helper(n, 0, columnVal); return count; } public void DFS_helper(int queensNum, int row, int[] columnVal) { if(row == queensNum)//已经遍历所有行了,得到结果 { count ++; } else { for(int i = 0; i < queensNum; i ++) { columnVal[row] = i; if(isValid(row, columnVal))//合法,就寻找下一行的位置,否则,变换当前行的值 { DFS_helper(queensNum, row+1, columnVal); } } } } public boolean isValid(int row, int[] columnVal) { for(int i = 0; i < row; i ++) { if(columnVal[i] == columnVal[row] || Math.abs(columnVal[row] - columnVal[i])== row - i) { return false; } } return true; } }