21,887
社区成员
发帖
与我相关
我的任务
分享
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
</head>
<body>
<?php
$num = 8; //几皇后?
echo showQueens(queen($num),$num);
/**
回溯主体函数,返回所有可能的方案数组
*/
function queen($num){
$queen=array(); //临时的一种方案
$queens=array();//全部方案
for($i=0;$i<$num;$i++){//从00位置开始放置皇后
for($j=0;$j<$num;$j++){
if(is_conflict($queen,$i,$j,$num)){ //有冲突则取下一个
if($j+1===$num){ //列到了再后一个都有冲突则回退
backRow($queen,$i,$j,$num);
countinue;
}
}else{ //没有冲突则前进
$queen[$i][$j]=1; //记录可行值
if($i===$num-1){ //前面到了最后一行,达成一种方案,记录。。
$queens[]=$queen;
unset($queen[$i]);
backRow($queen,$i,$j,$num);//回退
}else{
break;
}
}
}
}
return $queens;
}
function backRow(&$queen,&$i,&$j,$num){
$i=$i-1;
$j=getNextJ($queen[$i]);//求回退位置的J的下标
unset($queen[$i]);
if($j+1===$num){ //回退的行已经是最后一列了,接着回退
$i=$i-1;
if($i===-1){ //回退到了第一行,遍历结束
$i=$num;return;
}
$j=getNextJ($queen[$i]);
unset($queen[$i]);
}
}
function getNextJ($queen){
foreach($queen as $k=>$v){
return $k;
}
return false;
}
/**
显示打印结果
*/
function showQueens($queens,$num){
$html ='<div>'.$num.'皇后共'.count($queens).'种方案</div>';
foreach($queens as $queen){
$html .=showQueen($queen,$num);
}
return $html;
}
//图形显示
function showQueen($queen,$num){
$html ='<table style="text-align:center;">
<tr>';
for($i=-1;$i<$num;$i++){
$html .='<td width="52" height="52">'.$i.'</td>';
}
$html .='</tr>';
foreach($queen as $row=>$q){
$html .='<tr><td height="52">'.($row).'</td>';
for($i=0;$i<$num;$i++){
$html .='<td style="background-color:#00cc99;">'.$q[$i].'</td>';
}
$html .='</tr>';
}
$html .='</table>';
return $html;
}
/**
检查要前进i,j的位置上面有没有冲突
*/
function is_conflict($queen,$i,$j,$num){
$flag=check_conflict_col($queen,$i,$j); //竖列有没有冲突
if($flag)return $flag;
$flag=check_conflict_corner_left($queen,$i,$j); //左上对角有没有冲突
if($flag)return $flag;
$flag=check_conflict_corner_right($queen,$i,$j,$num); //右上对角有没有冲突
return $flag;
}
//竖列有冲突?
function check_conflict_col($queen,$i,$j){
for($row=0;$row<$i;$row++){
if($queen[$row][$j]===1){
return true;
}
}
return false;
}
//左上斜线有冲突?
function check_conflict_corner_left($queen,$i,$j){
$step=1;
while($i-$step>=0 && $j-$step>=0){
if($queen[$i-$step][$j-$step]===1){
return true;
}
$step++;
}
return false;
}
//右上斜线有冲突?
function check_conflict_corner_right($queen,$i,$j,$num){
$step=1;
while(($i-$step)>=0 && ($j+$step<$num)){
if($queen[$i-$step][$j+$step]===1){
return true;
}
$step++;
}
return false;
}
?>
</body>