8皇后問題描述:是一個古老而著名的問題,是回溯演算法的典型例題。該問題是十九世紀著名的數學家高斯1850年提出:在8X8格的國際象棋上擺放八個皇后,使其不能互相攻擊,即任意兩個皇后都不能處於同一行、同一列或同一斜線上,問有多少種擺法。 高斯認為有76種方案。1854年在柏林的象棋雜誌上不同的作者發表了40種不同的解,後來有人用圖論的方法解出92種結果。
此處以8皇后進行測試。
/**
* N皇后問題(回溯法)
*
* @author yundixiaoduo(4080509)
* @version 2.00
*/
public class NQueen {
int standard = 8;
// 棋盤格局儲存變數,採用一維數組來儲存。
// 其中索引為行號,值為列號。
// 均從0開始排。
private int[] broad = new int[standard];
NQueen(int standard) {
this.standard = standard;
for (int i = 0; i broad[i] = -1;
}
}
// 記錄輸出棋盤格局的個數,方便列印函數調用。
private int num = 0;
/**
* 回溯自測試函數
*
* @param row
* 當前遞迴所在行,從0開始。
*/
public void test(int row) { // 當row溢出(row的範圍為[0,standard-1]),表明找出一個解。
// 進行列印,並返回上一行(回溯)。
if (row == standard) { print();
return;
}
// 遍曆一行,先將皇后放到該行某一列上,然後進行檢驗。
// 若通過檢驗,則進入下一行(遞迴)。
// 若未通過,則返回到上一行(回溯)。
for (int i = 0; i standard; i++) { broad[row] = i;
if (check(row)) { test(row + 1);
}
}
}
/**
* 列印函數 將每種可能的棋盤布局列印輸出。 其中0代表空,1代表皇后。
*/
public void print() { num++;
System.out.println("-------第" + num + " 種------"); for (int column : broad) { for (int i = 0; i standard; i++) { if (column == i) { System.out.print(1 + " ");
} else { System.out.print(0 + " ");
}
}
System.out.println();
}
System.out.println();
}
/**
* 檢驗函數 檢驗是否符合N皇后的規則。
*
* @param row
* 所在行。
* @return boolean
* 若符合規則則返回true,若不符合則返回false。
*
*/
public boolean check(int row) { // 遍曆所有已下子,通過與已下子對比,查看該新位置是否符合規則。
// 因為是一行一行的下子,且每行只下一子,故不用考慮是否會有行衝突。
// 此處 i 可以當做已下子所在行來理解。
for (int i = 0; i // 檢驗是否有列衝突。
// 其中broad[i]表示遍曆已下皇后中的某行皇后所在列。
// broad[row]表示剛剛下的皇后所在列。
if (broad[i] == broad[row])
return false;
// 檢驗是否有斜線衝突。
// 假設將皇后放入座標系中,則處於同一斜線上的皇后所構成的直線斜率為1,
// 即橫座標差的絕對值與縱座標差的絕對值相等。
if (Math.abs(broad[row] - broad[i]) == row - i)
return false;
}
return true;
}
public static void main(String[] args) { NQueen queen = new NQueen(8);
queen.test(0);
}
}
運行結果: