1、回溯法
用一维数组记录皇后的位置。数组的下标代表皇后所处的行,下标对应的值代表皇后所处的列。用count记录皇后的个数,当count小于queen数时,在循环体中寻找合适位置的queen。寻找queen:从列1依次寻找,满足条件则count+1,继续从列1处寻找下一个queen。如全部找完没找到合适的位置,则count-1,从第count个皇后所在列的下一位置开始继续循环。
public class Queen { public void queenInstance(int num ) { if (num < 1 ) throw new IllegalArgumentException(); // store the position of the queen int[] queen = new int[num + 1]; // store the queen count int count = 1; queen[ count] = 1 ; while (count > 0 ) { while ((count <= num ) && (queen [count ] <= num)) { if (! isValid( queen, count )) queen[ count] ++; else { count++; if( count <= num) queen[ count] = 1 ; } } if (count > num ) { for (int i = 1; i <= num ; i++ ) System. out.println ("(" + i + ", " + queen[i] + ")") ; break; } count--; queen[ count] ++; } } private boolean isValid(int a [], int count) { for (int i = 1; i < count ; i++ ) if (a [i ] == a[ count] || ( i - count == a[ i] - a [count ]) || (i - count == a [count ] - a[ i])) return false; return true; } public static void main(String ... args) { Queen queen = new Queen (); queen. queenInstance(8); }
2、位运算法
考虑到我们寻找皇后是按照行的顺序依次寻找,因此在程序中,行的信息可以省略,每次的寻找实际上是为了在列中找到一个合适的位置。因此我们用一个int值(当然long也可以),将其第1到列总数的位置为1。这里我们通过将1左移num位减去1得到。函数test方法的三个参数分别是:皇后占用的位、左对角线皇后占用的位、右对角线皇后占用的位置。每次递归中,首先判断row是否等于upplim,等于则说明所有位被皇后占用,递归结束,得到一个解。若不相等,寻找可用的位(upplim & ~(row | ld | rd)),然后判断是否为0,为0说明全被占用,递归结束,未寻找到可行解。若不为0,则依次把所有可以放置皇后的位放置皇后,然后调用递归方法。
package algorithm; public class Queen { private int upplim; private int sum; private int queen[]; private int count; public void queenCalculate(int num) { if (num < 1 || num > 31) throw new IllegalArgumentException(); upplim = (1 << num) - 1; sum = 0; queen = new int[num + 1]; count = 1; test(0, 0, 0); } private void test(int row, int ld, int rd) { if (row != upplim) { // row不满,即皇后未放置完全 int pos = upplim & ~(row | ld | rd); // 寻找空闲位置 while (pos != 0) { // 仍有可以放置皇后的位置 int p = pos & -pos; // 取出最右边的1 pos -= p; // 把皇后放在最右边的1的位置 // 记录位置用于打印输出 int i = 0; while(p != (1 << i)) i++; queen[count++] = i + 1; test(row + p, (ld + p) << 1, (rd + p) >> 1); // 对下一行调用递归方法 } } else { sum++; for (int i = 1; i < count ; i++ ) System. out.print("(" + i + ", " + queen[i] + ")") ; System.out.println(); } count--; } public static void main(String... args) { Queen queen = new Queen(); queen.queenCalculate(8); System.out.println(queen.sum + " "); } }