钢条切割算法
某公司出售一段长度为i英寸的钢条的价格为p(i)如一次为{1,5,8,9,10,17,17,20,24,29},求给出一段长度为n的钢条,怎么切才能得到最佳收益?
对于这个问题,可以先切为两段,然后取最好的情况,第一段长度为i,则第二段为n-i,那么情况就有 i=1..n 共n种情况.
for(i=1;i<=n;i++)
{
q= maxmax(q, p(i)+cut_rod(n-i));
}
切除了i长,那么还剩n-i长,只需求出对n-i长的钢条如何切割,可以递归求解.
用递归算法来求解,时间复杂度为n^2,损耗较大
于是做了改进,将每次计算的结果保存下来,每次切割时如果已经有结果则不再计算.
int memorized_cut_rod_aux(int n,int * r)
{
int i;
int q=NEG_INF; //设为负无穷
if (r[n]>=0) return r[n];
if (n==0) return 0;
for(i=1;i<=n;i++)
{
q= maxmax(q, p(i)+cut_rod(n-i));
}
r[n]=q;
return q;
}
int memoized_cut_rod(int n)
{
int * r=(int*)malloc(sizeof(int)*(n+1));
int i;
int q=NEG_INF;
for(i=0;i<=n;i++)
{
r[i]=NEG_INF;
}
q=memorized_cut_rod_aux(n,r);
free(r);
return q;
}
上面的代码对递归算法做了改进,但是递归栈的调用损耗也比较大.
所以有进一步改进,所以有了从底向上法.由于n的切割必然需要n-1的切割,所以从1开始计算,并且每次计算时把结果保存起来.
时间复杂度为多项式级别
int bottom_up_cut_rod(n){
int * r=(int*)malloc(sizeof(int)*(n+1));
int i,j,q;
r[0]=0;
for(j=1;j<=n;j++)
{
q=NEG_INF;
for(i=1;i<=j;i++)
{
q=maxmax(q,p(i)+r[j-i]);
}
r[j]=q;
}
return r[n];
}
再一次改进,加入了存储第一次切割的长度的功能,可以求出长度为n的钢条切割的切割路径.
`
//拓展的从底向上完成,可以存储第一次切割的长度
int extended_bottom_up_cut_rod(n){
int * r=(int*)