N皇后問題是一個典型的約束求解問題,利用遞歸機制,可以很快的得到結果。
N皇后問題的描述:
在一個n*n的棋盤上,擺放n個皇后,要求每個皇后所在行、列、以及兩個對角線上不能出現其他的皇后,否則這些皇后之間將會相互攻擊。如下圖所示。
利用遞歸機制,可以很容易的求解n皇后問題。針對八皇后,總共有92種解。下面將給出N-皇后問題的一般求解代碼,在這里代碼是使用java編碼的。
總共設計了三個類,一個是皇后類(Queen),一個棋盤類(Board),一個是求解主程序類(NQueens)。具體代碼如下:
1: import java.util.ArrayList;
2: import java.util.List;
3:
4: public class NQueens {
5:
6: private int numSolutions;//求解結果數量
7: private int queenSize;//皇后的多少
8: private Board board;//棋盤
9: private List<Queen> queens = new ArrayList<Queen>();//皇后
10: //private List<Queen> nQueens = new ArrayList<Queen>();
11:
12: public NQueens(){
13:
14: }
15:
16: public NQueens(int size){
17: numSolutions = 0;
18: queenSize = size;
19: board = new Board(queenSize);
20: for (int i = 0; i < queenSize; i++) {
21: Queen queen = new Queen();
22: queens.add(queen);
23: }
24:
25: }
26:
27: public void solve(){
28: System.out.println("Start solve....");
29: putQueen(0);
30: }
31:
32: private void putQueen(int index){
33:
34: int row = index;
35: //如果此列可用
36: for (int col = 0; col < board.getQueenSize(); col++) {
37: if (board.getLayout()[row][col] == 0) {
38: //將皇后的位置置為此列位置
39: queens.get(row).setPosition(col);
40: //然后將相應的位置(此列的正下方以及兩個對角線)加1(即使其不可用)
41: for (int i = row + 1; i < board.getQueenSize(); i++) {
42: board.getLayout()[i][col] ++;
43: if (row + col - i >= 0) {
44: board.getLayout()[i][row + col - i] ++;
45: }
46: if (i + col - row < board.getQueenSize()) {
47: board.getLayout()[i][i + col - row] ++;
48: }
49: }
50:
51: if (row == board.getQueenSize()-1) {
52: numSolutions++;
53: printSolution(numSolutions);
54: }else {
55: putQueen(row + 1);
56: }
57: //回溯,將相應的位置(此列的正下方以及兩個對角線)減1
58: for (int i = row + 1; i < board.getQueenSize(); i++) {
59: board.getLayout()[i][col] --;
60: if (row + col - i >= 0) {
61: board.getLayout()[i][row + col - i] --;
62: }
63: if (i + col - row < board.getQueenSize()) {
64: board.getLayout()[i][i + col - row] --;
65: }
66: }
67:
68: }
69: }
70: }
71: //打印求解結果
72: private void printSolution(int i){
73: System.out.println("The "+i+ " solution is:");
74: for (int j = 0; j < board.getQueenSize(); j++) {
75: for (int k = 0; k < board.getQueenSize(); k++) {
76: System.out.print(queens.get(j).getPosition() == k ? " * ":" - ");
77: }
78: System.out.println();
79: }
80: System.out.println();
81: }
82: /**
83: * @param args
84: */
85: public static void main(String[] args) {
86: //可以改變參數
87: NQueens nQueens = new NQueens(8);
88: nQueens.solve();
89:
90: }
91:
92:
93:
94: }
95: import java.io.Serializable;
96:
97: //皇后類
98: public class Queen implements Serializable, Cloneable {
99:
100: /**
101: *
102: */
103: private static final long serialVersionUID = 7354459222300557644L;
104: //皇后的位置
105: private int position;
106:
107: public Queen(){
108:
109: }
110:
111: public int getPosition() {
112: return position;
113: }
114:
115: public void setPosition(int position) {
116: this.position = position;
117: }
118:
119: public Object clone() throws CloneNotSupportedException {
120:
121: return super.clone();
122: }
123: }
124:
125: import java.io.Serializable;
126:
127: //棋盤類
128: public class Board implements Serializable,Cloneable {
129:
130: /**
131: *
132: */
133: private static final long serialVersionUID = -2530321259544461828L;
134:
135: //棋盤的大小
136: private int queenSize;
137:
138: //棋盤的布局
139: private int[][] layout;
140:
141: public Board(int size){
142: this.queenSize = size;
143: this.layout = new int[queenSize][queenSize];
144: //初始化,使棋盤所有位置都可用,即全部置為0
145: for (int i = 0; i < queenSize; i++) {
146: for (int j = 0; j < queenSize; j++) {
147: layout[i][j] = 0;
148:
149: }
150: }
151: }
152:
153: public int getQueenSize() {
154: return queenSize;
155: }
156:
157: public void setQueenSize(int queenSize) {
158: this.queenSize = queenSize;
159: }
160:
161: public int[][] getLayout() {
162: return layout;
163: }
164:
165: public void setLayout(int[][] layout) {
166: this.layout = layout;
167: }
168:
169: public Object clone() throws CloneNotSupportedException {
170:
171: return super.clone();
172: }
173:
174: }
175: