问题描述:一家公司购买长钢条,将其切割成短钢条出售,假设切割本身没有成本,长度为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<stdio.h>
#include<time.h>
#include<stdlib.h>
const int N=10;
struct type{
int i;//长度
int price;//价格
float value;//单位长度的价值
};
void sort(type a[]){//冒泡法排序,按单位长度价值从高到低排序
int i,j;
for(i=0;i<N;i++){
for(j=0;j<N-i-1;j++){
if(a[j].value<a[j+1].value){
type temp=a[j];
a[j]=a[j+1];
a[j+1]=temp;
}
}
}
// for(i=0;i<N;i++){
// printf("%d、长度为%d的钢条,单位价值为%.2f\n",i+1,a[i].i,a[i].value);
// }
}
int greedy(type a[],int n){
int j;
int count[10]={0};//存储段数
int maxrevenue=0;//初始化最大收益
sort(a);
for(j=0;j<N;j++)
{
if(n>=a[j].i)
{
n-=a[j].i;//更新剩余长度
maxrevenue+=a[j].price;//更新最多收益
count[j]++;
if(n>=a[j].i) j--;//如果钢条长度大于等于性价比最高的长度,j--再次进行循环
}
}
printf("\n切割方案为:\n");
for(j=0;j<N;j++){
if(count[j]!=0){
printf("长度为%d的钢条%d段.\n",a[j].i,count[j]);
}
}
return maxrevenue;
}
int main()
{
int n;//钢条长度
type a[N];
// srand((unsigned)time(NULL));
for(int i=0;i<N;i++){//随机数生成,初始化钢条信息
a[i].i=i+1;
if(i==0){
a[i].price=1;
}else{
a[i].price=a[i-1].price+rand()%5;
}
a[i].value=(float)a[i].price/a[i].i;
}
printf("钢条长度:");
for(int i=0;i<10;i++) printf("%5d",a[i].i);
printf("\n钢条价格:");
for(int i=0;i<10;i++) printf("%5d",a[i].price);
printf("\n输入你要裁剪的钢条长度:");
scanf("%d",&n);
if(n<1)
{
printf("请输入正确的长度。\n");
return 1;
}
int maxrevenue = greedy(a,n);
printf("\n长度为%d的钢条最大收益为:%d\n",n,maxrevenue);
}