zoukankan      html  css  js  c++  java
  • 【算法】算法中的趣味数学(一)

    小续

       以下是我收集的一些有趣的计算实例,希望能够提高读者的编程水平及分析问题/解决问题的能力

    ---------------------------------------------

    马克思手稿中的数学题

      马克思手稿中有一道趣味数学题:有30个人,其中有男人、女人和小孩,在一家饭馆吃饭共花了50先令。若每个男人花3先令,每个女人花2先令,每个小孩花1先令。问男人、女人和小孩各有几人?

       实例解析:

       设x,y,z分别代表男人、女人和小孩的人数。按题目要求,可得到下面方程:

                      x + y + z = 30                (1)

                      3x + 2y + z = 50              (2)

       (2)-(1)可得

                      2x + y = 20                  (3)

       由(3)式可知,x的变化范围是1~10 (根据题意,男人、女人、小孩都有,故x、y、z都不能为0)。  

        程序如下:

    #include <stdio.h>
    int main()
    {
        int x,y,z,count = 0;
        clrscr();
        puts(" >> The solutions are:");
        printf("  No.      Men     Women   Children
    ");
        printf("--------------------------------
    ");
        for(x = 1; x <= 10; x++)
        {
            y = 20 - 2*x;                   //由(3)式求y
            z = 30 – x - y;                //由(1)式求z
            if(3*x + 2*y + z == 50 && y && z) //当前组合是否满足式(2)
            printf(" <%2d> | %2d | %2d | %2d
    ", ++count,x,y,z);
        }
        printf("--------------------------------
    ");
        printf(" Press any key to quit...");
        getch();
        return 0;
    }

    配对新郎和新娘

      3对情侣参加婚礼,3个新郎为A、B、C,3个新娘为X、Y、Z。有人不知道谁和谁结婚,于是询问了6位新人中的3位,但听到的回答是这样的:A说他将和X结婚;X说她的未婚夫是C;C说他将和Z结婚。这人听后知道他们在开玩笑,全是假话。请编程确认谁和谁是一对。

      实例解析:

      分表将A、B、C用1,2,3表示,将X和A结婚表示为“X == 1”,将Y不与A结婚表示为“Y !=1”,按题目叙述可写出下列表达式:

            X != 1           A不与X结婚

            X != 3           X的未婚夫不是C

            Z != 3           C不与Z结婚

      穷举满足以上条件所有可能的情况。

      程序如下:

    #include <stdio.h>
    int main()
    {
        int x,y,z;
        puts(" >> The solutions are:");
        printf("-------------------------------------
    ");
        for(x = 1; x <= 3; x++)          //穷举x的全部可能配偶
            for(y = 1; y <= 3; y++)        //穷举y的全部可能配偶
                for(z = 1; z <= 3; z++)      //穷举z的全部可能配偶
                    if(x!=1 && x!=3 && z!=3 && x!=y && x!=z && y!=z)
                    {
                        printf("X will marry to %c.
    ", 'A'+x-1);
                        printf("Y will marry to %c.
    ", 'A'+y-1);
                        printf("Z will marry to %c.
    ", 'A'+z-1);
                    }
        printf("--------------------------------------
    ");
        printf(" Press any key to quit...");
        getch();
        return 0;
    }

    分糖果

      10个小孩围成一圈分糖果,老师分给第一个小孩10块,第二个小孩2块,第三个小孩8块,第四个小孩22块,第五个小孩16块,第六个小孩4块,第七个小孩10块,第八个小孩6块,第九个小孩14块,第十个小孩20块。然后所有的小孩同时将手中的糖分一半给右边的小孩,糖块为奇数的可向老师再要一块。问这样的操作经过几次,大家手中的糖一样多?每人有多少块糖?

      实例解析:

      分糖过程是一个机械的重复过程。算法完全可以按照描述的过程进行模拟。

      程序如下:

    #include <stdio.h>
    void print(int s[]);
    int judge(int c[]);
    int j = 0;
    int main()
    {
        int sweet[10] = {10,2,8,22,16,4,10,6,14,20};
        int i, t[10], k;
        printf("Child No.  1   2  3  4  5  6  7  8  9  10
    ");
        printf("-------------------------------------
    ");
        printf("Round No.|
    ");
        print(sweet);               //输出每个人手中糖的块数
        while(judge(sweet))
        {      //若不满足要求则继续进行循环
            for(i = 0; i < 10; i++) 
                t[i] = sweet[i] = sweet[i]/2; //每个人手中的糖分成两半
            for(k = 0; k < 9; k++)
            { 
                sweet[k+1] = sweet[k+1] + t[k]; //分出的一半糖给右边
                if(sweet[k+1]%2!=0)
                    sweet[k+1]++;
            }
            sweet[0] += t[9];
            if(sweet[0]%2!=0)
                sweet[0]++;
            print(sweet);             //输出当前每个孩子中手中的糖数
        }
        printf("-------------------------------------
    ");
        printf("
     Press any key to quit...");
        getch();
        return 0;
    }
    int judge(int c[])
    {
        int i;
        for(i = 0; i < 10; i++)   //判断每个孩子手中的糖是否相同
        if(c[0] != c[i])
                return 1;          //不相同返回 1
        return 0;
    }
      
    void print(int s[])      //输出数组中每个元素的值
    {
        int k;
        printf("      <%2d> | ", j++);
        for(k = 0; k < 10; k++)
            printf("%4d", s[k]);
        printf("
    ");
    }

    波瓦松的分酒问题

      法国著名数学家波瓦松(Poison)在青年时代研究过一个有趣的数学问题:某人有12品脱的啤酒一瓶,想从中倒出6品脱,但他没有6品脱的容器,仅有一个8品脱和5品脱的容器,怎样才能将啤酒分成两个6品脱呢?

      实例解析:

      将12品脱酒用8品脱和5品脱的空瓶平分,可以抽象为解不定方程:

                   8x - 5y = 6

      其意义是:从12品脱的瓶中向8品脱的瓶中倒x次,并且将5品脱瓶中的酒向12品脱的瓶中倒y次,最后在12品脱的瓶中剩余6品脱的酒。

      分别用a,b,c代表12品脱、8品脱和5品脱的瓶子,求出不定方程的整数解,按照不定方程的意义则倒酒法为:

          a→b→c→a

           x     y

      倒酒的规则如下:

      (1)按a→b→c→a的顺序;

      (2) b倒空后才能从a中取;

      (3) c装满后才能向a中倒。

      程序如下:

    #include <stdio.h>
    void getti(int a, int y, int z);
    int i;           //最后需要分出的重量
    int main()
    {
        int a, y, z;
        printf(">>Input Full bottle a,Empty y,z, and Get volumes i:
    ");
        //a第一个瓶的容量  y:第二个瓶的容量  z:第三个瓶的容量
        printf(" >> ");
        scanf("%d%d%d%d", &a, &y, &z, &i);
        getti(a, y, z);           //按a -> y -> z -> a的操作步骤
        printf("
     Press any key to quit...");
        getch();
        return 0;
    }
    void getti(int a, int y, int z)
    //a:第一瓶的容量  y:第二个瓶的容量 z:第三个瓶的容量
    {
        int b = 0, c = 0, j = 0;  // b:第二瓶酒重  c:第三瓶酒重 j: 步数
        puts(" >> The division steps are as follows.
    ");
        printf(" Bottle:    a<%d> b<%d> c<%d>
    ",a,y,z);
        printf("-----------------------------
    ");
        printf(" Step No.|
    ");
        printf("   <%d>   | %4d %4d %4d
    ",j++,a,b,c);
        while(a!=i && b!=i && c!=i )
        { //当三个瓶的酒都!=i
            if(!b)
            {           //如果第二瓶为空,则从第一瓶倒入第二瓶
                a -= y;
                 b = y; 
            }
            else if(c == z)
            {     //如果第三瓶满,则将第三瓶倒入第一瓶中
                a += z;
                c = 0; 
            }
            else  if(b > z-c)
            {  //如果第二瓶的酒>第三瓶的剩余空间
                b -= (z-c);  //由第二瓶倒满第三瓶,第二瓶保留剩余部分
                c = z; 
            }
            else
            {          //将第二瓶全部倒入第三瓶中
                c += b;
                b = 0;
            }
            printf("   <%d>   | %4d %4d %4d
    ",j++,a,b,c);
        }
        printf("-----------------------------
    ");
    }

    本文出自 “成鹏致远” 博客,请务必保留此出处http://infohacker.blog.51cto.com/6751239/1171360

  • 相关阅读:
    Linux文件和目录的属性及权限
    chkconfig原理
    Linux启动过程
    正则表达式(grep,awk,sed)和通配符
    Linux系统目录结构:目录层次标准、常用目录和文件
    Linux系统目录结构
    虚拟机快照和克隆
    Linux系统的基础优化
    Linux系统应用管理:增加普通用户(密码管理等)
    [译]java9新特性:在接口中用pirvate方法让default(java8接口特性)更简练
  • 原文地址:https://www.cnblogs.com/lcw/p/3159444.html
Copyright © 2011-2022 走看看