问题描述
八皇后问题,是一个古老而著名的问题,是回溯的典型案例。该问题是国际西洋棋棋手马克斯·贝瑟尔于1848年提出:在8X8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。
问题分析
对于八皇后的求解可采用回溯算法,从上至下依次在每一行放置皇后,进行搜索,若在某一行的任意一列放置皇后均不能满足要求,则不再向下搜索,而进行回溯,回溯至有其他列可放置皇后的一行,再向下搜索,直到搜索至最后一行,找到可行解,输出。可以使用递归函数实现上述回溯算法,递归函数用于求解在某一行放置皇后
那么,我们应该怎么做呢?其实步骤不太难:
(1)在第n行寻找可以插入的位置,中间涉及到位置合法性的判断
(2)如果没有可以插入的位置,返回
(3)如果有可以插入的位置, 插入数据。此时再判断是否已经是最后一行,如果是,打印输出返回;反之继续对下一行数据进行试探处理。
php代码
public static $gEightQueen = array(0,0,0,0,0,0,0,0);
public static $gCount=0;
//打印八皇后结果
private function display($gEightQueen){
for($outer = 0; $outer <8; $outer ++){
for($inner = 0; $inner < $gEightQueen[$outer]; $inner ++) echo "# ";
echo "@ ";
for($inner = $gEightQueen[$outer] + 1; $inner < 8; $inner ++) echo "# ";
echo "<br>";
}
echo "===========================<br>";
}
//位置合法性判断
private function check_position_valid($loop,$value){
for($index=0; $index<$loop; $index++) {
$data = $this->gEightQueen[$index];
//位于同一列
if($data == $value) {
return 0;
}
//反向对角线
if(($loop+$value) == ($data+$index)){
return 0;
}
//正向对角线
if(($loop-$value) == ($index-$data)){
return 0;
}
}
return 1;
}
private function eight_queen($index){
for($loop=0; $loop<8; $loop++) {
if($this->check_position_valid($index,$loop)) {
$this->gEightQueen[$index] = $loop;
//判断是否已经是最后一行
if($index == 7){
$this->gCount++;
echo $this->gCount."解法<br>";
$this->display( $this->gEightQueen);
return 1;
}
$this->eight_queen($index+1);
}
}
}
public function eight_queen_result(){
$this->eight_queen(0);
}