问题:给定一段长度为n英寸的钢条和一个价格表pi(i=1,2,...,n),求切割钢条方案,使得销售收益rn最大。如果长度为n英寸的钢条的价格pn足够大,最优解可能就是完全不需要切割。
方法一:递归
从上而下把所有的全部搜索一遍
int CUT_ROD(int p[],int n)
{
if(n==0)
return 0;
int q=INT_MIN;
for(int i=1;i<=n;i++)
{
q=max(q,p[i]+CUT_ROD(p,n-i));
printf("n=%d",n-i);
}
printf(" q=%d",q);
printf("\n");
return q;
}
方法二:自顶而下的保存已计算子问题的递归复杂度o(n^2)
int a(int p[],int n,int r[])
{
int q;
if(r[n]>0)
return r[n];
if(n==0)
q=0;
else
{
q=INT_MIN;
for(int i=1;i<=n;i++)
q=max(q,p[i]+a(p,n-i,r));
}
r[n]=q;
return q;
}
int MEMOIZED_CUT_ROD(int q[],int n)
{
int *r=(int *)malloc(sizeof(int)*n);
for(int i=1;i<=n;i++)
r[i]=INT_MIN;
return a(q,n,r);
}
方法三:动态规划
动态规划是自底而上的一种方法,通过for循环实现,在求某个问题时候,它的所有子问题都已经求出。这部分算法导论p209页讲解十分精彩。
而且为了输出方案,利用重构解进行输出。
代码如下
#include<stdio.h>
#include<stdlib.h>
typedef struct cut
{
int *r;
int *s;
}cut;
void initialize(cut *mycut,int n)
{
mycut->r=(int *)malloc(sizeof(int)*n);
mycut->s=(int *)malloc(sizeof(int)*n);
}
cut* T(int p[],int n)
{
cut *mycut=(cut *)malloc(sizeof(cut));
initialize(mycut,n);
mycut->r[0]=0;
for(int j=1;j<=n;j++)
{
int q=INT_MIN;
for(int i=1;i<=j;i++)
{
if(q<p[i]+mycut->r[j-i])
{
q=p[i]+mycut->r[j-i];
mycut->s[j]=i;
}
}
mycut->r[j]=q;
}
return mycut;
}
void PRINT_CUT_ROD_SOLUTION(int p[],int n)
{
int i=1;
cut *mycut=(cut *)malloc(sizeof(cut));
initialize(mycut,n);
mycut=T(p,n);
while(n>0)
{
printf("第%d段长度是%d ",i,mycut->s[n]);
i++;
n=n-mycut->s[n];
}
}
int main(void)
{
cut *mycut=(cut *)malloc(sizeof(cut));
printf("长度n为多少:");
int n;
scanf("%d",&n);
initialize(mycut,n);
int *p=(int *)malloc(sizeof(int));
int i=1;
printf("输入不同长度对应的价格,以#结束\n");
int key;
while(scanf("%d",&key)==1)
{
p[i++]=key;
}
mycut=T(p,n);
printf("max=%d",mycut->r[n]);
PRINT_CUT_ROD_SOLUTION(p,n);
return 0;
}
结果:
长度i 1 2 3 4 5 6 7 8 9 10
价格pi 1 5 8 9 10 17 17 20 24 30
原文地址:http://blog.csdn.net/wodeai1625/article/details/46003355