这是我的第一个博文,心情先小激动一下
----------------------------分割线-----------------------------
《编程之美》书中提到,用动态规划的方法比较好。假设x1,x2,x3,x4,x5分别为每一卷书的数量,因为书的价格是一样的,所以他们的顺序是不影响答案的。这里我们可以按照由大到小的顺序把它排序,即x1>=x2>=x3>=x4>=x5。书中同样给出了解释说,对于不同的组合,动态规划的方法可以找到最优解。打个比方也就是说,取了1,1,1,1,0,之后,求得的最优解,和取了1,1,1,0,1之后的最优解是一样的。同理其他亦然。所以就用x1-1,x2-1,x3-1,x4-1,x5来代替扣除四本书的所有情况。
程序如下:
#include<stdio.h>
#include<stdlib.h>int large=100000;//用一个比较大的值来补充min()中的五个参数。
float min(float x1,float x2,float x3,float x4,float x5)
{
float a[5]={x1,x2,x3,x4,x5};
float real_min=a[0];
for(int i=0;i<5;i++)
{
if(a[i]<real_min)
real_min=a[i];
}
return real_min;
}
int temp;
void resort(int c[5])//冒泡法从小到大排序
{
for(int i=5-1;i>0;i--)
for(int j=0;j<i;j++)
{
if(c[j]>c[j+1])
{
temp=c[j];
c[j]=c[j+1];
c[j+1]=temp;
}
}
}
float F(int x1,int x2,int x3,int x4,int x5)
{
int c[5]={x1,x2,x3,x4,x5};
resort(c);
x1=c[4];//x1最大
x2=c[3];
x3=c[2];
x4=c[1];
x5=c[0];
if(x5>0)
return min(
5*8*(1-0.25)+F(x1-1,x2-1,x3-1,x4-1,x5-1),
4*8*(1-0.2)+F(x1-1,x2-1,x3-1,x4-1,x5),
3*8*(1-0.1)+F(x1-1,x2-1,x3-1,x4,x5),
2*8*(1-0.05)+F(x1-1,x2-1,x3,x4,x5),
8+F(x1-1,x2,x3,x4,x5)
);
else if(x5==0&&x4>0)
return min(
4*8*(1-0.2)+F(x1-1,x2-1,x3-1,x4-1,x5),
3*8*(1-0.1)+F(x1-1,x2-1,x3-1,x4,x5),
2*8*(1-0.05)+F(x1-1,x2-1,x3,x4,x5),
8+F(x1-1,x2,x3,x4,x5),large
);
else if(x5==0&&x4==0&&x3>0)
return min(
3*8*(1-0.1)+F(x1-1,x2-1,x3-1,x4,x5),
2*8*(1-0.05)+F(x1-1,x2-1,x3,x4,x5),
8+F(x1-1,x2,x3,x4,x5),large,large
);
else if(x5==0&&x4==0&&x3==0&&x2>0)
return min(
2*8*(1-0.05)+F(x1-1,x2-1,x3,x4,x5),
8+F(x1-1,x2,x3,x4,x5),large,large,large
);
else if(x5==0&&x4==0&&x3==0&&x2==0&&x1>0)
return 8+F(x1-1,x2,x3,x4,x5);
else
return 0;
}
int main()
{
int b[5];
printf("请输入5本书的数量:\n");
for(int i=0;i<5;i++)
scanf("%d",&b[i]);
float min_money=F(b[0],b[1],b[2],b[3],b[4]);
printf("最终花费:%f\n",min_money);
system("pause");
}