赞
踩
在《算法导论》动态规划那章,讲述了一个应用动态规划的例子--钢条切割。
钢条切割的问题是这样的:给定一段长度为n英寸的钢条和一个价格表(i=1,2,...,10),求切割钢条方案,使得销售收益最大。
我们可以采用一种简单的递归求解方法:我们将钢条从左边切割下长度为i的一段,只对右边剩下的 长度为n-i的一段继续进行切割(递归求解),对左边的一段则不再进行切割。用公式可以表示为:
方法一:带备忘的自顶向下法。
此方法按自然的递归形式编写过程,但过程会保存每个子问题的解,这里我们保存在数组r中。当需要一个子问题的解时,过程首先检查是否已经保存过此解。如果是,则直接返回保存的值,从而节省计算时间;否则,按通常形式计算这个子问题。我们称这个递归过程是带备忘的(memoized),因为它“记住”了之前已经计算的结果。代码如下:
- #include<iostream>
- using namespace std;
-
- //对应于长度为1,2...10的钢条价格表
- int p[10]={1,5,8,9,10,17,17,20,24,30};
-
- //返回两个数的较大值
- int max(int a,int b)
- {
- return (a>b)?a:b;
- }
-
- /*首先检查所需值是否已知,如果是,则直接返回保存的值。
- 否则,用通常方法计算所需值q,然后将此值存入r[n]。值得注意的
- 是,笔者在此处没有对钢条的长度n进行限制,所以n可能大于10,
- 于是增加了自己的判断,若n大于10,则计算n-10的子序列*/
- int MemoizedCutRodAux(int p[],int n,int r[])
- {
- if(r[n]>=0)
- return r[n];
- int q;
- if(n==0)
- q=0;
- else
- {
- q=-1;
- for(int i=0;i<n;i++)
- {
- if(i<10)
- q=max(q,p[i]+MemoizedCutRodAux(p,n-1-i,r));
- else
- q=max(q,r[10]+MemoizedCutRodAux(p,n-1-10,r));
- }
- }
- r[n]=q;
- return q;
- }
-
- int main()
- {
- int n;
- cout<<"请输入钢条的长度:";
- cin>>n;
- //将辅助数组的r[0..n]元素均初始化为-1
- int *r=new int[n+1];
- for(int i=0;i<=n;i++)
- {
- r[i]=-1;
- }
- int sum=MemoizedCutRodAux(p,n,r);
- cout<<"最大收益为:"<<sum<<endl;
- return 0;
- }
运行结果:
方法二:自底向上法
这种方法一般需要恰当定义子问题规模的概念,使得任何子问题的求解都只依赖于“更小的”子问题的求解。因而我们可以将子问题按规模排序,按由小至大的顺序进行求解。当求解某个子问题时,它所依赖的那些更小的子问题都已求解完毕,结果已经保存。每个子问题只需求解一次,当我们求解它时,它的所有前提子问题都已经求解完成。
- #include<iostream>
- using namespace std;
-
- //对应于长度为1,2...10的钢条价格表
- int p[10]={1,5,8,9,10,17,17,20,24,30};
-
- //返回两个数的较大值
- int max(int a,int b)
- {
- return (a>b)?a:b;
- }
-
- /*首先创建一个新数组r来保存子问题的解,然后将r[0]初始化为0,因为长度为0的钢条没有收益
- 接着对j=1,2,...,n按升序求解每个规模为j的子问题。将规模为j的子问题的解存入r[j]。最后返回r[n],即最优解*/
- int BottomUpCutRod(int p[],int n)
- {
- int *r=new int[n+1];
- r[0]=0;
- for(int j=1;j<=n;j++)
- {
- int q=-1;
- for(int i=0;i<=j;i++)
- {
- if(i<10)
- q=max(q,p[i]+r[j-i-1]);
- else
- q=max(q,r[10]+r[j-10-1]);
- }
- r[j]=q;
- }
- return r[n];
- }
-
- int main()
- {
- int n;
- cout<<"请输入钢条的长度:";
- cin>>n;
- int sum=BottomUpCutRod(p,n);
- cout<<"最大收益为:"<<sum<<endl;
- return 0;
- }
运行结果为:
赞
踩
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。