• 有两艘船需要装运的n箱货物,第一艘船的载重量是c1,第二艘船的载重量是c2,wi是货箱i的重量,且w1+w2+……+wn<=c1+c2


    (1) 问题描述: 
           有两艘船和需要装运的n个货箱,第一艘船的载重量是c1,第二艘船的载重量是c2,wi是货箱的质量,且w1+w2+...+wn <= c1+c2. 
    希望确定是否有一种可将所有n个货箱全部装船的方法。若有的话,找出该方法。 

    (2) 举例描述: 
           当n=3,c1=c2=50,w=[10,40,40]时,可将货箱1、2装到第一艘船上,货箱3装到第二艘船上。 
           但是如果w=[20,40,40],则无法将货箱全部装船。由此可知问题可能有解,可能无解,也可能有多解。 
       
    (3) 问题分析 
           虽然是关于两艘船的问题,其实只讨论一艘船的最大装载问题即可。因为当第一艘船的最大装载为bestw时, 
    若w1+w2+...+wn-bestw <= c2,则可以确定一种解,否则问题就无解。这样的问题转化为第一艘船的最大装载问题。 

     (4) 算法设计 
           转化为一艘船的最优化问题后, 问题的解空间为一个子集树。也就是算法要考虑所有物品取、舍情况的组合, 
    n个物品的取舍组合共有2的n次方个分支。 

           1> 和回溯算法的思想一样,用FIFO分支搜索所有的分支,并记录已搜索分支的最优解,搜索完子集树也就找出了问题的解。 
       
           2> 要想求出最优解,必须搜索到叶结点,所以要记录数的层次。当层次为n+1时,搜索完全部叶结点,算法结束。 

           3> 分支搜索过程中活结点的"层"是需要标识的,否则入队后无法识别结点所在的层。每处理完一层让"-1"入队,以此来标识 
              "层",并用变量i来记录当前层。 

           4> 每个活结点要记录当前船的装载量。

    代码示例:

      1 <?php
      2 class Queue
      3 {
      4     private $queue = array();
      5     
      6     /**
      7      * 入栈
      8      */
      9     public function push($val)
     10     {
     11         array_push($this->queue, $val);
     12     }
     13     
     14     /**
     15      * 出栈
     16      */
     17     public function pop()
     18     {
     19         $value = array_shift($this->queue);
     20         return $value;
     21     }
     22     
     23     /**
     24      * 判断是否为空栈
     25      */
     26     public function is_empty()
     27     {
     28         if(empty($this->queue))
     29         {
     30             return true;
     31         } else {
     32             return false;
     33         }
     34     }
     35 }
     36 
     37 class BranchLimitFIFOSearch
     38 {
     39     private $n;//n个货箱
     40     private $c1;//第一艘船的载重量
     41     private $c2;//第二艘船的载重量
     42     private $bestw;//第一艘船的最大载量
     43     private $ew = 0;//当前船的装载量
     44     private $w;//货箱质量数组 array
     45     private $s = 0;//所有货箱的重量之后
     46     private $queue;//FIFO队列
     47     
     48     /**
     49      * 构造函数
     50      */
     51     public function __construct($n, $c1, $c2, $w)
     52     {
     53         $this->n = $n;
     54         $this->c1 = $c1;
     55         $this->c2 = $c2;
     56         $this->w = $w;
     57         $this->s = is_array($w) ? array_sum($w) : 0;
     58         $this->queue = new Queue();
     59     }
     60     
     61     /**
     62      * 最忧装载值
     63      * @param $c 第一艘船的载重量
     64      */
     65     public function max_loading($c)
     66     {
     67         $i = 1;//E-节点的层
     68         $this->ew = 0;//当前船的装载量
     69         $this->bestw = 0;//目前的最优值
     70         $this->queue->push(-1);
     71         
     72         while(!$this->queue->is_empty())//搜索子集空间树
     73         {
     74             if($this->ew + $this->w[$i] <= $c)//检查E-节点的左孩子,货箱i是否可以装载
     75             {
     76                 $this->add_live_node($this->ew + $this->w[$i], $i);//货箱i可以装载
     77             }                                                                                                                                  
     78             $this->add_live_node($this->ew, $i);
     79             
     80             $this->ew = $this->queue->pop();//取下一个节点
     81             
     82             if(-1 == $this->ew)
     83             {
     84                 if($this->queue->is_empty())
     85                 {
     86                     break;
     87                 }
     88                 $this->queue->push(-1);
     89                 $this->ew = $this->queue->pop();//取下一个节点
     90                 $i++;
     91             }
     92         }
     93         
     94         return $this->bestw;
     95     }
     96     
     97     /**
     98      * 入队
     99      */
    100     public function add_live_node($wt, $i)
    101     {
    102         if($this->n == $i)//是叶子
    103         {
    104             $this->bestw < $wt && $this->bestw = $wt;
    105         } else {//不是叶子
    106             $this->queue->push($wt);
    107         }
    108     }
    109     
    110     /**
    111      * 所有货箱的重量
    112      */
    113     public function get_s()
    114     {
    115         return $this->s;
    116     }
    117     
    118     /**
    119      * 获取最优值
    120      */
    121     public function get_bestw()
    122     {
    123         return $this->bestw;
    124     }
    125 }
    126 
    127 function branch_limit_FIFO_search()
    128 {
    129     $n = 3;
    130     $c1 = 50;
    131     $c2 = 50;
    132     $w = array(0,10,40,40);
    133     $bfis = new BranchLimitFIFOSearch($n, $c1, $c2, $w);
    134     $s = $bfis->get_s();//所有货箱的重量之后
    135     
    136     if($s<=$c1 || $s<=$c2)
    137     {
    138         die("need only one ship!");
    139     }
    140     if($s > $c1+$c2)
    141     {
    142         die("no solution!");
    143     }
    144     
    145     $bfis->max_loading($c1);
    146     $bestw = $bfis->get_bestw();
    147     if($s-$bestw <= $c2)
    148     {
    149         echo "The first ship loading " . $bestw . "<br/>";
    150         echo "The second ship loading " . ($s - $bestw);
    151     } else {
    152         echo "no solution!!!";
    153     }
    154 }
    155 
    156 branch_limit_FIFO_search();
    View Code
  • 相关阅读:
    进程之锁机制, 信号机制, 事件机制
    进程相关内容01
    计算机相关知识
    网络编程------socketserver模块以及socket模块的更多用法.
    网络编程------粘包问题以及切换目录
    简单工厂模式
    SQL LinqToSql Lambda
    检测到有潜在危险的 Request.Form 值
    轻量级ORM 利用T4模板 批量生成多文件 实体和业务逻辑 代码
    最全前端资源汇集
  • 原文地址:https://www.cnblogs.com/573583868wuy/p/7237061.html
Copyright © 2020-2023  润新知