时光绘梦集
位置:首页PHP正文

道法自然 2025/03/04 周2

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就可以了。代码更短更容易维护。


上一篇:php路由转发
下一篇:svg图片链接