n皇后问题很简单,它是一个循环+递归实现回溯算法的一个很好示例。
外层循环保证列方向遍历,内层递归保证行方向遍历。综合起来便可遍历整个搜索空间。
解决问题的关键是知道要保存什么。
递归中要保存的是前面几层的位置信息,以及当前递归层数。
位置信息用于判断是否冲突。递归层数用于判断递归是否结束。
怎么判断是否冲突?这就需要对矩阵的信息存储有所了解。
矩阵同行,同列都好判断,那么同一主对角线,同一副对角线怎么判断?
同一主对角线上行号与列号之和都相等。同一副对角线上行号与列号之差都相等。
知道了这些,N皇后就不难写出了。
下面给出java实现代码。
1 package com.company; 2 3 /** 4 * n皇后问题实际上很简单。 5 * Created by zqiguo on 2017/2/28. 6 */ 7 public class NQueens { 8 9 /** 10 * count用于计数解法个数。 11 */ 12 private static int count = 0; 13 14 /** 15 * n皇后递归函数 16 * @param n 皇后个数 17 * @param row 当前行号 18 * @param pos 前row-1 行放置的皇后位置信息。比如(0,pos[0]),表示第0行皇后放置在第pos[0]列。 19 */ 20 private static void nQueens(int n, int row, int[] pos){ 21 if (row == n){ 22 count++; 23 return; 24 } 25 for (int i = 0; i < n; i++) { 26 int conflictFlag = 0; 27 for (int j = 0; j < row; j++) { 28 if (i == pos[j] || pos[j] - j == i - row || pos[j] + j == i + row){ 29 conflictFlag = 1; 30 } 31 } 32 if (conflictFlag == 0){ 33 pos[row] = i; 34 nQueens(n,row+1,pos); 35 } 36 } 37 } 38 39 /** 40 * n皇后外部调用接口, 返回解法个数 41 * @param n 皇后个数 42 * @return 解法个数 43 */ 44 public static int nQueens(int n){ 45 int[] pos = new int[n]; 46 nQueens(n,0,pos); 47 return count; 48 } 49 50 public static void main(String[] args){ 51 System.out.println(nQueens(8)); 52 } 53 }
最近知乎上有一股邪风,说什么1行实现某某算法。以我个人来看,代码效率与可读性最重要。有时可读性还要在效率之上。
那些标榜1行实现某某某的,代码可还能看?更何况不换行,不加{},就是1行实现了?