二、实验内容
问题描述:我国古代数学家张丘建在《算经》中出了一道题“鸡翁一,值钱五;鸡母”一,值钱三;鸡雏三,值钱一。百钱买百鸡,问鸡翁、鸡母、鸡雏各几何?”。现在假定各鸡种的价格不变,拥有的钱数为m,需要购买的鸡数为n,试求出所有可能的购买方案总数和每种方案详情。
输入:每行对应一个测试样例,每一行包含2个数字,分别为n和m。
输出:输出可能购买方案总数,并输出每种方案详情。
进一步要求:先用常规嵌套循环解决,并验证当输入n=m=10000时的程序执行时间。在此基础上改进算法,提高算法时间复杂度。
程序代码:
#include<stdio.h>
int main()
{
int N, M, n1, n2, n3, iCount = 0,k=1;//n1,n2,n3分别为鸡翁、鸡母、鸡雏的数目;拥有的钱数M,需购买鸡数N
printf("请输入拥有的总钱数以及需购买的鸡数(注:输入‘-1’表示完成输入)\n");
scanf("%d %d", &N, &M);
while (N != -1) //-1:表示输入结束
{
iCount = 0;
for (n1 = 0; n1 < N; n1++)
for (n2 = 0; n2 < N; n2++)
for (n3 = 0; n3 < N; n3++)//枚举对象三元组
if ((n1 + n2 + n3 == N) && (5 * n1 + 3 * n2 + n3 / 3.0 == M))//验证
iCount++;
printf("共有%d种可行方案\r\n", iCount);
scanf("%d%d", &N, &M);
}
for (n1 = 0; n1 <= 20; n1++)
for (n2 = 0; n2 <= 33; n2++)
for (n3 = 3; n3 <= 99; n3++)
if (n1 * 5 + n2 * 3 + n3 / 3 == 100)
if (n1 + n2 + n3 == 100)
if (n3 % 3 == 0)
{
printf("方案% d:", k++);
printf("鸡翁:%d只,鸡母:%只,鸡雏:%d只 \n", n1, n2, n3);
}
return 0;
}
程序测试及运行结果:
分析与讨论:
首先设n1,n2,n3分别为鸡翁、鸡母、鸡雏的数量。
由于题中条件的限制,我们可以估算出公鸡,母鸡,小鸡的数量范围。
由于题中条件的限制,即:
若全买公鸡,最多买100/5=20只,显然:0<x<20;
同理:0<y<33 0<z<100;
约束条件:x+y+z=100且 5x+3y+z/3=100且小鸡数量是3的倍数;
若用上面算法,需要枚举尝试20*33*100=66000次,算法的效率太低。因此我们将算法加以改进:即:在公鸡(x),母鸡(y)数量确定后,根据总数100只,小鸡的数量z也就确定为:z=100一x-y,无需再对小鸡的数量进行枚举,此时的约束条件:5x+3y+z/3=100 且小鸡的数量是3的倍数,这样只需枚举20*34=660次。
由上述实例可以看出,枚举法是蛮力策略的一种变现形式,也是一种使用非常普遍的思维方法。然而对于同一个问题,可以选择不同的美居范围,不同的枚举对象,这样解决问题的效率差别可能会很大。所以选择合适的方法会让解决问题的效率大大提高。