前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >动态规划算法 ——钢条切割问题

动态规划算法 ——钢条切割问题

作者头像
用户1327360
发布2018-07-27 11:24:05
8220
发布2018-07-27 11:24:05
举报
文章被收录于专栏:决胜机器学习决胜机器学习

动态规划算法

——钢条切割问题

(原创内容,转载请注明来源,谢谢)

一、问题

长度为n米的钢条,需要切割成x断来贩卖。假设没有切割成本,且每种长度能够销售的价格是一个确定的值(例如长度1米可以卖1元,长度2米可以卖5元,长度3米可以卖6元等)。

现在假定已知每种长度可以销售的价格,求长度为n米的钢条切割后,可以销售得到的最大利润。

二、分析

对于任意长度为i米的钢条,要获得最大价值,要么不需要切割整个i来售卖,要么从左开始切割i’米(这一段不再切割),使得i’米的价格加上剩余i-i’米切割后的价格的总和最大。

三、解法一

根据分析可知,可以遍历不同的长度,并且取得最终的最大值。

代码如下:

public function solvingSlowDynamic($prices, $length)

{

$pricesCount = count($prices);

//待售长度为0的钢条,或价格表只有长度为0的价格,

if(empty($length) || 1 >= $pricesCount)

{

return 0;

}

$salePrice = 0;

//从切割长度为1开始,逐个计算价格

for($i = 1;$i < $pricesCount-1; $i++)

{

$salePrice = max($salePrice, $prices[$i] + $this->solvingSlowDynamic($prices, $length-$i));

}

return $salePrice;

}

四、解法二

解法一有个问题,当钢条长度太长时,计算会很慢。因为会重复计算许多中间节点的长度最佳售价。例如长度为10的钢条,从左切可以是0-10、1-9、2-8、3-7...,要计算9的售价则又需要计算0-9、1-8、2-7、3-6...,可以看到长度为2、3等的钢条,其价格需要重复计算。

易知,长度为n的钢条,有2^n种切割方案,故需要计算2^n次长度的售价。

为了加快速度,可以把中间结果缓存。

代码如下:

private $lengthPrices = array();//用于缓存中间计算结果

public function solvingFastDynamic($prices, $length)

{

//如果已经有缓存的结果则直接返回

if(isset($this->lengthPrices[$length]))

{

return $this->lengthPrices[$length];

}

$pricesCount = count($prices);

if(empty($length) || 1 >= $pricesCount)

{

return 0;

}

$salePrice = 0;

for($i = 1;$i < $pricesCount-1; $i++)

{

$salePrice = max($salePrice, $prices[$i] + $this->solvingSlowDynamic($prices, $length-$i));

}

//缓存计算结果

$this->lengthPrices[$length] = $salePrice;

return $salePrice;

}

五、解法三

除了缓存中间结果,还可以采用自底向上的方式计算,即先计算长度为0、1、2、3...的,则在计算长度为n的钢条时,可以直接利用前面的计算结果进行计算。

代码如下:

public function solvingNewDynamic($prices, $length)

{

//自底向上,计算出每个长度的最佳售价

$lengthPrices = array(0 => 0);

//记录每种长度下的最左端切割长度

$cutLength = array(0 => 0);

$pricesCount = count($prices);

for($i = 1;$i < $pricesCount-1; $i++)

{

$salePrice = 0;

for($j = 1; $j <= $i; $j++)

{

$tmpSum = $prices[$j] + $lengthPrices[$i-$j];

if($salePrice < $tmpSum)

{

$salePrice = $tmpSum;

//记录长度为i的钢条的最佳第一段切割长度

$cutLength[$i] = $j;

}

}

//记录长度为i的最佳售价

$lengthPrices[$i] = $salePrice;

}

return array($lengthPrices, $cutLength);

}

上面的解法中,除了计算出每个长度的最佳售价,还计算出每个长度的最左端的切割方案。实际中,如果需要长度为n的切割方案,则根据数组可以查出第一段的切割长度,假设为i,则此时再查表,找到长度为i的钢条的第一段切割方案。以此类推,推算出最终的切割方案。

——written by linhxx 2018.05.13

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2018-05-13,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 爱思考的coder 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档