有两艘船需要装运的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> 每个活结点要记录当前船的装载量。
代码示例:
<?php
class Queue
{
private $queue = array(); /**
* 入栈
*/
public function push($val)
{
array_push($this->queue, $val);
} /**
* 出栈
*/
public function pop()
{
$value = array_shift($this->queue);
return $value;
} /**
* 判断是否为空栈
*/
public function is_empty()
{
if(empty($this->queue))
{
return true;
} else {
return false;
}
}
} class BranchLimitFIFOSearch
{
private $n;//n个货箱
private $c1;//第一艘船的载重量
private $c2;//第二艘船的载重量
private $bestw;//第一艘船的最大载量
private $ew = 0;//当前船的装载量
private $w;//货箱质量数组 array
private $s = 0;//所有货箱的重量之后
private $queue;//FIFO队列 /**
* 构造函数
*/
public function __construct($n, $c1, $c2, $w)
{
$this->n = $n;
$this->c1 = $c1;
$this->c2 = $c2;
$this->w = $w;
$this->s = is_array($w) ? array_sum($w) : 0;
$this->queue = new Queue();
} /**
* 最忧装载值
* @param $c 第一艘船的载重量
*/
public function max_loading($c)
{
$i = 1;//E-节点的层
$this->ew = 0;//当前船的装载量
$this->bestw = 0;//目前的最优值
$this->queue->push(-1); while(!$this->queue->is_empty())//搜索子集空间树
{
if($this->ew + $this->w[$i] <= $c)//检查E-节点的左孩子,货箱i是否可以装载
{
$this->add_live_node($this->ew + $this->w[$i], $i);//货箱i可以装载
}
$this->add_live_node($this->ew, $i); $this->ew = $this->queue->pop();//取下一个节点 if(-1 == $this->ew)
{
if($this->queue->is_empty())
{
break;
}
$this->queue->push(-1);
$this->ew = $this->queue->pop();//取下一个节点
$i++;
}
} return $this->bestw;
} /**
* 入队
*/
public function add_live_node($wt, $i)
{
if($this->n == $i)//是叶子
{
$this->bestw < $wt && $this->bestw = $wt;
} else {//不是叶子
$this->queue->push($wt);
}
} /**
* 所有货箱的重量
*/
public function get_s()
{
return $this->s;
} /**
* 获取最优值
*/
public function get_bestw()
{
return $this->bestw;
}
} function branch_limit_FIFO_search()
{
$n = 3;
$c1 = 50;
$c2 = 50;
$w = array(0,10,40,40);
$bfis = new BranchLimitFIFOSearch($n, $c1, $c2, $w);
$s = $bfis->get_s();//所有货箱的重量之后 if($s<=$c1 || $s<=$c2)
{
die("need only one ship!");
}
if($s > $c1+$c2)
{
die("no solution!");
} $bfis->max_loading($c1);
$bestw = $bfis->get_bestw();
if($s-$bestw <= $c2)
{
echo "The first ship loading " . $bestw . "<br/>";
echo "The second ship loading " . ($s - $bestw);
} else {
echo "no solution!!!";
}
} branch_limit_FIFO_search();
有两艘船需要装运的n箱货物,第一艘船的载重量是c1,第二艘船的载重量是c2,wi是货箱i的重量,且w1+w2+……+wn<=c1+c2的更多相关文章
- 分支界定法 branch-and-bound 分析与实现)(转载)
1. 介绍分支界定法之前需要了解一下广度优先搜索breadth-First-search(BFS) 1.从图中某个顶点V0出发,并访问此顶点:以层为顺序,一层一层往下遍历 2.从V0出发,访问V0的各 ...
- 【51nod-1596】搬货物
现在有n个货物,第i个货物的重量是 2wi .每次搬的时候要求货物重量的总和是一个2的幂.问最少要搬几次能把所有的货物搬完. 样例解释: 1,1,2作为一组. 3,3作为一组. Input 单组测试数 ...
- 51nod 1596 搬货物【贪心/二进制】
1596 搬货物 题目来源: CodeForces 基准时间限制:1 秒 空间限制:131072 KB 分值: 10 难度:2级算法题 收藏 取消关注 现在有n个货物,第i个货物的重量是 2wi ...
- 51nod1596 搬货物
现在有n个货物,第i个货物的重量是 2wi .每次搬的时候要求货物重量的总和是一个2的幂.问最少要搬几次能把所有的货物搬完. 样例解释: 1,1,2作为一组. 3,3作为一组. Input 单组测试数 ...
- BUG-FREE-For Dream
一直直到bug-free.不能错任何一点. 思路不清晰:刷两天. 做错了,刷一天. 直到bug-free.高亮,标红. 185,OA(YAMAXUN)--- (1) findFirstDuplicat ...
- BZOJ 1835: [ZJOI2010]base 基站选址 [序列DP 线段树]
1835: [ZJOI2010]base 基站选址 题目描述 有N个村庄坐落在一条直线上,第i(i>1)个村庄距离第1个村庄的距离为Di.需要在这些村庄中建立不超过K个通讯基站,在第i个村庄建立 ...
- 【Machine Learning in Action --4】朴素贝叶斯分类
1.概述 朴素贝叶斯分类是贝叶斯分类器的一种,贝叶斯分类算法是统计学的一种分类方法,利用概率统计知识进行分类,其分类原理就是利用贝叶斯公式根据某对象的先验 概率计算出其后验概率(即该对象属于某一类的概 ...
- E. Change-free
Student Arseny likes to plan his life for n days ahead. He visits a canteen every day and he has alr ...
- python机器学习实战(三)
python机器学习实战(三) 版权声明:本文为博主原创文章,转载请指明转载地址 www.cnblogs.com/fydeblog/p/7277205.html 前言 这篇notebook是关于机器 ...
随机推荐
- MyBatis动态传入表名
mybatis里#{}与${}的用法: 在动态sql解析过程,#{}与${}的效果是不一样的: #{ } 解析为一个 JDBC 预编译语句(prepared statement)的参数标记符. 如以下 ...
- python dpkt解析ssl流
用法:python extract_tls_flow.py -vr white_pcap/11/2018-01-10_13-05-09_2.pcap -o pcap_ssl_flow.txt & ...
- weblogic修改安装路径教程
我们有一个安装好的weblogic,我们想再装一个weblogic或者想把weblogic装到别的目录去,最直接的做法是从头装一个. 但是从头装一个是比较费时费力的,尤其是打补丁环节和创domain环 ...
- 微信小程序FAQ
1. 图片名注意大小写. 不然本地预览是可以看到的.上传后用手机就看不到了. 2. bindtap等事件传参 wxml <view id="tapTest" data-hi= ...
- git上传新建项目
新建立本地项目,现在需要上传到git.对上传过程归纳如下: 一 在gitlab中新建项目:如下图所示: 二,新建后获取url地址,在本地打开gitbash,根据url把git上的项目clone到本地: ...
- 由@Convert注解引出的jackson对枚举的反序列化规则
对于一些状态字段以前时兴用常量,现在时兴用枚举,虽然阅读体验极佳,但是传值的时候还是会有些麻烦,需要设置一下转换器.比如: class A{ @Convert(converter=TestTypeCo ...
- Linux第二周作业
通过反汇编一个简单的C程序,分析汇编代码理解计算机是如何工作的 1.进入vi编写C语言程序代码,首先必须输入命令vi main,c,其中main.c是文件名. 紧接着按esc键退出编辑状态,再输入一个 ...
- ASP.Net MVC(1) 之走进MVC
一.MVC三层架构: mvc三层架构,大家都比较熟悉了,这里再介绍一下.Mvc将应用程序分离为三个部分: Model:是一组类,用来描述被处理的数据,同时也定义这些数据如何被变更和操作的业务规则.与数 ...
- windows下的pycharm配置 linux环境
由于最近学习python的需要,为了方便程序的调试,尝试在Windows下的Pycharm远程连接到虚拟机中Centos下的python环境.(这里我采用的是ssh的远程连接)1.准备工作: 固定ce ...
- docker pure-ftpd
FROM alpine:3.7ADD http://dl-4.alpinelinux.org/alpine/edge/testing/x86_64/pure-ftpd-1.0.47-r0.apk /r ...