钢条切割问题——递归求解法

本文探讨了钢条切割问题,该问题旨在最大化长度为n英寸的钢条的销售收益。通过递归方法,我们得到公式rn = max(pi + rn-i, rn),其中pi是长度为i的钢条收益,rn-i是剩余部分的最优收益。然而,递归方法在n较大时效率低下,指数级增长。为了解决这个问题,文章提出了使用动态规划进行优化,以更高效地找到最优钢条切割策略。" 109681608,10210680,Python函数详解:类型、参数、作用域与递归,"['Python', '函数', '递归']

这道题在算法导论(第三版)的204页

钢条切割问题是这样的:

给定一段长度为n英寸的钢条和一个价格表pi(i=1,2,...,n),求切割钢条方案,使得销售收益rn最大。注意,如果长度为n英寸的钢条的价格pn足够大,最优解可能就是完全不需要切割。


假设有一张价格表为:

价格表
长度i12345678910
价格pi1589101717202430


基本思路:我们将钢条从左边切割下长度为i的一段,只对右边剩下的长度为n-i的一段继续进行切割(递归求解),对左边的一段则不再进行切割。则可得公式:

                    

其中pi为左边长度为i的钢条的收益,rn-i为右边长度为n-i的钢条继续切割后得到的最优收益,rn为长度为n的钢条切割后得到的最优收益。


递归实现代码如下:

package dynamic;

/*
 * 钢条切割  算法导论P204
 */
public class Steel {

	/**
	 * 比较大小
	 * @param a
	 * @param b
	 * @return
	 */
	public static int max(int a, int b) {
		 return (a > b ? a : b);
	}
	
	/**
	 * 
	 * @param p 存储价格的数组,p从0开始存储
	 * @param n 钢条长度为n
	 * @return 返回长度为n的钢条切割后得到的最大收益
	 */
	public static int cut(int[] p,int n){
		//如果长度为0,则0收益
		if(n==0)
			return 0;
		int q = -1;
		// 思路:
		//将长度为n的钢条从左切割长度为i的一段,则右端为长度为n-i的一段
		//其中长度为i的左端不继续切割,只继续切割右端的那一部分
		//一直递归的cut(p,n-i)最后得到的是长度为n-i的钢条切割后的最大收益
		for(int i = 0; i < n; i++) {
			q = max(q,p[i] + cut(p,n-i-1));	//切割后的收益和不切割
		}
		return q;
	}
	
	public static void main(String[] args) {
		int[] p = {1,5,8,9,10,17,17,20,24,30};
		int n = 4;
		System.out.println(cut(p,n));
	}

}


因为这道题是用递归实现的,所以必然存在一个缺点,那就是当数据n很大时,方法cut会反复调用相同的参数值对自身进行递归调用,即它反复求解相同的子问题。这会导致cut方法运行时间为n的指数函数。效率很低!

所以我们需要进行优化,可以使用动态规划法来求解最优钢条切割问题。

如何利用动态规划法来求解最优钢条切割问题请见下文。



评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值