《算法设计与分析》实验报告(二)之m钱买n鸡

二、实验内容

问题描述:我国古代数学家张丘建在《算经》中出了一道题“鸡翁一,值钱五;鸡母”一,值钱三;鸡雏三,值钱一。百钱买百鸡,问鸡翁、鸡母、鸡雏各几何?”。现在假定各鸡种的价格不变,拥有的钱数为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次。

由上述实例可以看出,枚举法是蛮力策略的一种变现形式,也是一种使用非常普遍的思维方法。然而对于同一个问题,可以选择不同的美居范围,不同的枚举对象,这样解决问题的效率差别可能会很大。所以选择合适的方法会让解决问题的效率大大提高。

  • 7
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

了一li

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值