• 算法笔记-分支界限法


      (1)广度优先

         说明: 

              

      代码:

     1 <?php
     2 
     3 $arr = [
     4     'A' => [
     5         'B' => [
     6             'D' => ['H', 'I'],
     7             'E' => ['J'],
     8             'F',
     9         ],
    10         'C' => ['G'],
    11     ],
    12 ];
    13 
    14 //直接用数组遍历
    15 //print_R(bfsArr($arr));
    16 
    17 
    18 //先将数组转成树, 再遍历
    19 //$tree = current(buildTree($arr));
    20 //$queue = [$tree->val];
    21 //print_r(bfsObj([$tree]));
    22 
    23 
    24 function bfsArr($queue) {
    25     static $res;
    26     $val = key($queue);
    27     $out = array_shift($queue);
    28     if (is_array($out)) {
    29         $res[] = $val;
    30         $queue = array_merge($queue, $out);
    31     } else {
    32         $res[] = $out;
    33     }
    34     
    35     if (!empty($queue)) {
    36         bfsArr($queue);
    37     }
    38     return $res;
    39 }
    40 
    41 function bfsObj($queue) {
    42     static $res;
    43     $out = array_shift($queue);
    44     $res[] = $out->val;
    45     $queue = array_merge($queue, $out->nodes);
    46     
    47     if (!empty($queue)) {
    48         bfsObj($queue);
    49     }
    50     return $res;
    51 }
    52 
    53 
    54 function buildTree($arr) {
    55     $ret = array();
    56     if (is_array($arr)) {
    57         foreach ($arr as $k => $v) {
    58             if (is_numeric($k)) {
    59                 $tree = nodeFactory($v);
    60             } else {
    61                 $tree = nodeFactory($k);
    62                 $tree->nodes = buildTree($v);  
    63             }
    64             $ret[] = $tree;
    65         }
    66     } else {
    67         return nodeFactory($arr);
    68     }
    69     return $ret;
    70 }
    71 
    72 
    73 function nodeFactory($val) {
    74     $node = new stdClass();
    75     $node->val = $val;
    76     $node->nodes = array();
    77     return $node;
    78 }

      (2)0-1背包

         说明: 

       代码:

    <?php
    $weights = [2, 5, 4, 2];
    $values = [6, 3, 5, 4];
    $limit = 10;
    print_r( bfs());
    
    function bfs($queue = []) {
        static $res;
        global $values;
        
        $node = (array)array_shift($queue);
        $val = celSum($node, $values);
        $res[$val][] = $node;
        $queue = array_merge($queue, childNodes($node));
        
        if (!empty($queue)) {
            bfs($queue);
        }
        ksort($res);
        return end($res);
    }
    
    function childNodes($node) {
        global $weights, $values, $limit;
        static $maxVal;
        
        $childNodes = array();
        $nextKey = count($node);
        if (!isset($values[$nextKey])) {
            return array();
        }
        
        //剩余的都装进去的价值
        $fill = array_fill($nextKey, count($weights) - $nextKey, 1);
        $allIn = array_merge($node, $fill);
        $allInVal = celSum($allIn, $values);
        if ($allInVal < $maxVal) {
            return array();
        }
        
        //当前总重量
        $weight = celSum($node, $weights);
        $value = celSum($node, $values);
        
        if ($weight + $weights[$nextKey] <= $limit) {
            $childNodes[] = array_merge($node, [$nextKey => 1]);
            $value += $values[$nextKey];
        }
        $childNodes[] = array_merge($node, [$nextKey => 0]);
        
        //更新最优值
        $maxVal = max($value, $maxVal);
        
        return $childNodes;
    }
    
    
    function celSum($queue, $values) {
        $sum = 0;
        foreach ($queue as $k => $v) {
            $sum += $v * $values[$k];
        }
        return $sum;
    }

     (3)旅行商问题

         说明: 

        

      代码:

     1 <?php
     2 $map = [
     3     [0, 15, 30, 5],
     4     [15, 0, 6, 12],
     5     [30, 6, 0, 3],
     6     [4, 12, 3, 0],
     7 ];
     8 
     9 $p = [1, 2, 3, 4];      //表示4个景点
    10 $begin = [1];
    11 print_r(bfs([$begin]));
    12 
    13 function bfs($queue) {
    14     static $res;
    15     $node = array_shift($queue);
    16     $childs = childNodes($node);
    17     empty($childs) && $res[celSum($node)][] = $node;
    18     $queue = array_merge($queue, $childs);
    19     
    20     if (!empty($queue)) {
    21         bfs($queue);
    22     }
    23     krsort($res);
    24     return end($res);
    25 }
    26 
    27 function childNodes($node) {
    28     global $p;
    29     $remaind = array_diff($p, $node);
    30     $childNodes = array();    
    31     foreach ($remaind as $v) {
    32         $childNodes[] = array_merge($node, [$v]);
    33     }
    34     return $childNodes;
    35 }
    36 
    37 function celSum($queue) {
    38     $distance = 0;
    39     foreach ($queue as $k => $p) {
    40         if (isset($queue[$k + 1])) {
    41             $distance += distance($queue[$k], $queue[$k + 1]);
    42         }
    43     }
    44     return $distance;
    45 }
    46 
    47 function distance($p1, $p2) {
    48     global $map;
    49     return $map[$p1 - 1][$p2 - 1];
    50 }

     (4)最优工程布线

         说明: 

          

       代码:

     1 <?php
     2 $map = [
     3     [0, 0, 0, 0, 0, -1],
     4     [0, 0, -1, 0, 0, 0],
     5     [0, 0, 0, -1, -1, 0],
     6     [0, -1, 0, 0, 0, 0],
     7     [0, 0, 0, 0, 0, 0],
     8 ];
     9 
    10 $a = [1, 0];
    11 $b = [3, 5];
    12 
    13 print_r(bfs([[$a]]));
    14 
    15 function bfs($queue) {
    16     global $b;
    17     static $res = array();
    18     $path = array_shift($queue);
    19     $nextPath = searchPath($path);
    20     
    21     //找到目标点
    22     if (in_array($b, $nextPath)) {
    23         array_push($path, $b);
    24         array_push($res, $path);
    25         $nextPath = [];
    26     }
    27     
    28     foreach ($nextPath as & $v) {
    29         $v = array_merge($path, [$v]);
    30     }
    31     $queue = array_merge($queue, $nextPath);
    32     
    33     //硬跑太吃内存了, 这里作个优化
    34     $queue = array_filter($queue, 'isContinue');
    35     $queue && bfs($queue);
    36     return $res;
    37 }
    38 
    39 function searchPath($path) {
    40     global $map;
    41     
    42     //上下左右四个点
    43     $end = end($path);
    44     $nodes = [
    45         [$end[0] + 1, $end[1]],
    46         [$end[0] - 1, $end[1]],
    47         [$end[0], $end[1] + 1],
    48         [$end[0], $end[1] - 1],
    49     ];
    50     return array_filter($nodes, function ($node) use ($path, $map){
    51         return isset($map[$node[0]][$node[1]]) && $map[$node[0]][$node[1]] === 0 && !in_array($node, $path);
    52     });
    53 }
    54 
    55 function isContinue($path) {
    56     //用于记录从出发点开始到其他点的最短距离
    57     static $min = array();
    58     $end = end($path);
    59     $len = count($path);
    60     $key = join('_', $end);
    61     
    62     if (isset($min[$key]) && $len > $min[$key]) {
    63         return false;
    64     } else {
    65         $min[$key] = $len;
    66         return true;
    67     }
    68 }
  • 相关阅读:
    计算机科学中最重要的32个算法
    趣事
    深度学习迷你地图
    物理学
    代数几何
    Node.js 文件系统
    Node.js 常用工具util包
    Node.js 全局对象
    favi.icon是什么?
    Node.js 路由
  • 原文地址:https://www.cnblogs.com/wangjianheng/p/12578967.html
Copyright © 2020-2023  润新知