php计算八皇后问题
今天去表弟家玩,他提到了八皇后摆放问题,我说直接用8个for循环镶套就可以解决,经过一番构思和测试,终于实现了输出八皇后位置。
因为每一行只能摆放一个皇后,所以我只求每个皇后的纵坐标。
经过多番修改成功生成92种结果,最终代码分享如下,留下纪念下。
<?php
for($a=1;$a<9;$a++){
$tmp[1]=$a;
for($b=1;$b<9;$b++){
$tmp[2]=$b;
if($b==$a){continue;}
if(
abs($b-$a)==1
){continue;}
for($c=1;$c<9;$c++){
$tmp[3]=$c;
if (in_array($c, array($a, $b))){
continue;
}
if(
abs($c-$b)==1||abs($c-$a)==2
){
continue;
}
for($d=1;$d<9;$d++){
$tmp[4]=$d;
if (in_array($d, array($a,$b,$c))){
continue;
}
if (
abs($d-$b)==2
||abs($d-$a)==3
||abs($d-$c)==1
){
continue;
}
for($e=1;$e<9;$e++){
$tmp[5]=$e;
if (in_array($e, array($a,$b,$c,$d))){
continue;
}
if (
abs($e-$b)==3
||abs($e-$a)==4
||abs($e-$c)==2
||abs($e-$d)==1
){
continue;
}
for($f=1;$f<9;$f++){
$tmp[6]=$f;
if (in_array($f, array($a,$b,$c,$d,$e))){
continue;
}
if (
abs($f-$b)==4
||abs($f-$a)==5
||abs($f-$c)==3
||abs($f-$d)==2
||abs($f-$e)==1
){
continue;
}
for($g=1;$g<9;$g++){
$tmp[7]=$g;
if (in_array($g, array($a,$b,$c,$d,$e,$f))){
continue;
}
if (
abs($g-$b)==5
||abs($g-$a)==6
||abs($g-$c)==4
||abs($g-$d)==3
||abs($g-$e)==2
||abs($g-$f)==1
){
continue;
}
for($h=1;$h<9;$h++){
$tmp[8]=$h;
if (in_array($h, array($a, $b,$c,$d,$e,$f,$g))){
continue;
}
if (
abs($h-$b)==6
||abs($h-$a)==7
||abs($h-$c)==5
||abs($h-$d)==4
||abs($h-$e)==3
||abs($h-$f)==2
||abs($h-$g)==1
){
continue;
}
$xx[]=$tmp;
}
}
}
}
}
}
}
}
print_r($xx);
上面的是简单版本,按照需求直接写的代码。
不过上面的代码,里面有很多类似的重复逻辑。最重优化后的版本如下,使用了递归的方式,不在一个一个的写for循环。
<?php
$arr = [];
bhh(1, [], [], $arr);
print_r($arr);
function bhh($length, $load, $jieguo, &$arr) {
if ($length > 8) {
$arr[] = $jieguo;
return;
}
for ($num = 1; $num <= 8; $num++) {
if (!in_array($num, $load) && isValid($num, $length, $jieguo)) {
$load[] = $num;
$jieguo[$length] = $num;
bhh($length + 1, $load, $jieguo, $arr);
array_pop($load);
}
}
}
function isValid($num, $length, $jieguo) {
foreach ($jieguo as $index => $value) {
$indexDiff = $length - $index;
$valueDiff = abs($num - $value);
if ($valueDiff === $indexDiff) {
return false;
}
}
return true;
}
这种方式的好处,比如如果求9皇后的问题呢,只要修改一下$length>9就可以了。代码更短更容易维护。