zoukankan      html  css  js  c++  java
  • 鸡兔同笼问题、百鸡问题、辗转相除法求最大公约数

    一、鸡兔同笼

    鸡和兔子35只,腿一共有94条,求出鸡和兔子的数量各是多少?(鸡的数目是23,兔子的数目是12)

    $n = 0;

    for($ i=1;$i<35;$i++){

      $n ++;    //n=34;

      $ j=35-i;

      if(i*2+j*4==94){

        printf("鸡的数目是%d只, 兔子的数目是%d只",$i,$j);

      }

    }

      此时,循环进行了34次。但是,有些循环是无意义的,因为得到了结果,循环还在继续往下执行。我们知道:两个未知数,两个方程,其方程组的解唯一!那么我们可以让流程控制的if语句在得到结果以后,终止循环!

    改进如下:

    $n = 0;

    for($ i=1;$i<35;$i++){

      $n ++;    //n=23;

      $ j=35-i;

      if(i*2+j*4==94){

        printf("鸡的数目是%d只, 兔子的数目是%d只",$i,$j);

        break;

      }

    }

      此时,循环只需要进行23次即可。再有,在确定循环变量的时候,分析:兔有四条腿,而鸡只有两只脚,兔子数明显比鸡的个数所得到的腿数更有效!(有点绕,大家不理解的看下面代码~)

    终极版改进如下:

    $n = 0;

    for($ i=1;$i<35;$i++){

      $n ++;    //n=12;

      $ j=35-i;

      if(i*4+j*2==94){

        printf("鸡的数目是%d只, 兔子的数目是%d只",$j,$i);

        break;

      }

    }

      最后,我们获得结果只需要循环12次!比起最开始的34次,节省了22次不必要的循环!可能大家觉得没什么,如果是循环一万次一百万次呢,不必要的循环多了,消耗的资源也就多了,获得最终结果的速度也慢了。

    二、百鸡问题

      张丘建在《算经》中提出了“百鸡问题”:鸡公一值钱五,鸡母一值钱三,鸡雏三值钱一,百钱买百鸡,问鸡公、母、雏各几何?

        先给大家罗列出结果:

          公鸡有0只,母鸡有25只,小鸡有75只
          公鸡有4只,母鸡有18只,小鸡有78只
          公鸡有8只,母鸡有11只,小鸡有81只
          公鸡有12只,母鸡有4只,小鸡有84只

    同样的,我们让计算机帮我们计算,代码如下:

    $n = 0;

    for($cocks = 0;$cocks <= 20;$cocks ++){

             for($hens = 0;$hens <= 33;$hens ++){

           $n++;    //n = 714;

                       $chicks = 100 - $cocks - $hens;

                       if(5*$cocks + 3*$hens + $chicks/3 == 100) {

                                printf("公鸡有%d只,母鸡有%d只,小鸡有%d只<br />",$cocks,$hens,$chicks);

                       }

             }

    }

      要想得到结果,计算机需要循环21*34=714次。接下来怎么优化呢?假设公鸡数为x,母鸡数为y,小鸡数为z。我们先把z消去,得7x+4y = 100,x = (100-4y)/7,那么x最大只能得到14,节省了(20-14)*34=204次循环!另外,我们可以发现,如果少买7只母鸡,就可多买4只公鸡和3只小鸡!我们是不是可以再得到最大的母鸡数,然后递减7,以及公鸡数+4、小鸡数+3来获取最终结果呢?

    代码如下:

    $n = 0;

    for($cocks = 0;$cocks <= 14;$cocks ++){

             for($hens = 33;$hens >=0;$hens --){

           $n++;    

                       $chicks = 100 - $cocks - $hens;

                       if(5*$cocks + 3*$hens + $chicks/3 == 100) {

                                printf("公鸡有%d只,母鸡有%d只,小鸡有%d只<br />",$cocks,$hens,$chicks);

              break;    //得到最大的母鸡数;

                       }

             }

       if(printf()){

         break;    //如果printf()有返回值,即内层循环得出了结果,那么就终止!;

       }

    }

      不知道为什么浏览器报错了。。。程序出现问题,待改进。

      1,break指的是从当前的中断语句开始算起,往外层循环中断的层数,默认是1。要想中断两层循环,break 2即可;

      2,查手册,得printf为字符串函数,原型为:int printf ( string $format [, mixed $args [, mixed $... ]] ),它有一个返回值,返回值为输出字符串的长度。浏览器报错为:Warning: printf() expects at least 1 parameter,即printf()期待至少一个参数在里面,而我没有写入参数;

      3,得到有结果就终止的方法也许不那么可靠,毕竟循环只进行了那么几次,我们不知道后续的执行情况如何。

      为了减少循环次数,优化代码,可以减少一层循环。定义的公鸡数$cocks从0开始,每次加1,换句话说,已经保证了$cocks为正整数!把小鸡数$chicks消去得到的等式,

    7x+4y = 100,y=(100-7x)/4,y也应该是一个正整数。若x、y确定了,z的值随之确定。只需要将x从0~14代入,y的表达式也同时为正整数即可。

      使用一层循环来求百鸡问题,代码如下:

    $n = 0;
    for($cocks = 0;$cocks<=14;$cocks++){
      $n++;    //n = 15;
      $hens = (100-7*$cocks)/4;
        if(is_int($hens)){
          printf("公鸡有%d只,母鸡有%d只,小鸡有%d只<br />",$cocks,$hens,100-$cocks-$hens);
        }
    }

      使用一层循环,只需要循环15次就能得到最终的结果。比起使用两层循环的714次,节省了699次。由此可得,我们在实际工作中,为了使代码更高效,尽可能地避免使用太多层的循环。

    三、辗转相除法求最大公约数

    $num1 = $_GET['n1'];

    $num2 = $_GET['n2'];

    $num = $num1;

    $div = $num2;

    //求余数,开始循环体

    do {

             $mod = $num % $div;

             // 刚才的除数就变成了被除数

            $num = $div;

            // 刚才的余数就变成了除数

            $div = $mod;

    }while($mod != 0);

    echo "最大公约数为:",$num;

  • 相关阅读:
    sql执行的顺序
    $(obj).index(this) 与 $(this).index()的区别
    java取得百分比
    取得input的特殊值
    清除select的边框和三角形
    在jsp页面中获取列表长度
    mysql mybatis 批量更新和新增
    oracle mybatis 批量更新和新增
    jstl if else 判断
    判断radio,select,checkbox是否选中的方法
  • 原文地址:https://www.cnblogs.com/Hansen32/p/6079719.html
Copyright © 2011-2022 走看看