- 对最优切割问题的分析
问题描述:一家公司购买长钢条,将其切割成短钢条出售,假设切割本身没有成本,长度为i的短钢条的价格为Pi。那给定一段长度为n的钢条和一个价格表Pi,求钢条的切割方案使得收益Rn最大。例如某公司以单价26元买到了一批长度为10的钢条,目前各长度钢条的市场价如下表所示:
长度i | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
价格Pi | 1 | 5 | 8 | 9 | 10 | 17 | 17 | 20 | 24 | 26 |
要求:随机生成钢条长度n和不同长度钢条的价格信息,编写程序确定一种钢条的切割方案,使公司的收益最大化。
使收益最大化就是将钢条切割成两段,然后求出这两段的价格最大值,就是最优解,随机生成长度和每段的价格,考虑所有可能。
- 算法选择以及设计思路
通常用于具有某种最优性质问题,对于本题而言,最后让求出收益的最大化。对于这个题
一方面体现了最优解又一方面体现了算法求解相同的子问题。使用动态规划算法时,用子问题的最优解来构造原问题的最优解和使用数组来保存子问题的解。动态规划与其他算法相比较而言,灵活性强,计算量大大减少了,但是对空间的需求增加了,本题因为所需空间不大,所以采用这种算法。
对于一个动态规划问题:
第一步就是先确定最优解的结构。如果一个问题的结构包含其子问题的最优解,就称此问题具有最优解的结构性质。使用动态规划算法时,用子问题的最优解来构造原问题的最优解。因此必须考查最优解中用到的所有子问题。
第二步定义最优解的计算公式。
第三步是根据得到的求解最优解公式,计算出结果。
第四步是构造出最优解。
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
int N[11]={};//存储价格
int r[11]={};
int upToDown(int);
int maxx(int a,int b);
int main()
{
int z,x,c,a[11]={0};
printf("钢条长度:");
for(z=0;z<=10;z++)
printf("%3d",z);
//随机数生成,生成不同钢条长度的不同价格
srand((unsigned)time(NULL));
for(z=0;z<=10;z++)
{
a[z]=rand()%(25)+4;
}
printf("\n");
for(z=0;z<=9;z++)
for(x=z+1;x<=10;x++)
{
if(a[z]>a[x])
{
c=a[z];
a[z]=a[x];
a[x]=c;
}
}
a[0]=0;
a[1]=1,a[2]=4,a[3]=7;
printf("钢条价格:");
for(z=0;z<=10;z++)
N[z]=a[z];
for(z=0;z<=10;z++)
printf("%3d",a[z]);
//对钢条进行切割计算
int current;
puts("\n输入你要裁剪的钢条长度:");
scanf("%d",¤t);
int i;
printf("%d长的钢条最大收益是:%d\n",current,upToDown(current));
printf("各个长度的收益情况:\n长度:");
for(i=0;i<=current;i++)
{
printf("%3d ",i);
}
printf("\n");
printf("收益:");
for(i=0;i<=current;i++)
{
printf("%3d ",r[i]);
}
}
int upToDown(int n) //每次返回的值是当前长度n的最大收益
{
if(n==0)
return 0;
int q=N[n];
int i;
for(i=1;i<n;i++)
q=maxx(q,r[i]+upToDown(n-i));
r[n]=q;
if(r[n]!=0)
return r[n];
return q;
}
int maxx(int a,int b)//比较大小
{
if(a>=b)
return a;
else
return b;}