破碎的砝码问题

来源:互联网 发布:网络视频监控施工方案 编辑:程序博客网 时间:2024/04/25 07:51
1.问题描述
    一天商人不小心把40磅重的砝码摔成4部分,发现4部分砝码的重量都是整磅数,而且可以用它们称出任意1-40之间的整数磅质量,问这四块砝码各重多少磅?

2.该问题的数学分析

   ①必须有1磅的砝码,否则39磅的重量无法称出.
   ②有了1磅的砝码后,再加上一个3磅的砝码,可称出2~4磅的重量.
   ③有了1磅和3磅的砝码后,再加上一个9磅的砝码,可称出5~13磅的重量.
   ④有了1、3、9磅的砝码后,再加上一个27磅的砝码,可称出14~40磅的重量.
   所以这4块砝码碎片分别是1、3、9、27磅,即首项为1,公比为3的等比数列.

    看了数学家的逻辑分析,是不是觉得很有道理,可就是不会,没关系,我们可以用很笨的计算机来算出答案。

3.编程解决问题
     首先对该问题抽象数学模型:设这四块砝码的质量分别为a, b, c, d;则有
   (1)a+b+c+d = 40(abcd为1-37之间的正整数,且互不相等)
   (2)abcd可以组合算出(只能加减)1-40之间的任意整数

4.分析问题
    (1) 对于(1)问题,a,b,c,d互补等于40且各不相等,一般的,我们会想到穷举法列出以下的程序(C语言):
     int a, b, c, d;
     int count = 0;

     for (a=1; a<=37; a++)
          for (b=1; b<=37; b++)
               for (c=1; c<=37; c++)

                   for (d=1; d<=37; d++)
                       if ( (a+b+c+d == 40) && (a!=b)&&(a!=c)&&(a!=d) &&(b!=c) &&(b!=d) &&(c!=d) )
                      {
                           count++;
                           printf("%d %d %d %d\n%d\n", a, b, c, d, count);
                       }
    实际上这样的方式不仅运算量较大,而且得出的答案会有4!种重复(实际会得出7128种答案),这是因为这种穷举考虑了排列方式,比如10,8,9,13实际上会出现4!种排列,所以很没有效率。下面这种经典的算法可以解决这个问题。
     int a, b ,c ,d;

     int count = 0;
     for (a=1; a<=40; a++)
          for (b=a+1; b<=40-a; b++)
               for (c=b+1; c<=40-a-b; c++)
                    for (d=c+1; d<=40-a-b-c; d++ )
                    if (a+b+c+d == 40)
                    {

                       count++;
                       printf("%d %d %d %d\n%d\n", a, b, c, d,count);
                    }
      count输出为297,这种算法的有趣之处在与它确保了内层循环搜索范围始终小于外层循环,而且不会出现数相等的情况。关于它的数学证明(暂时不懂,有兴趣可以查阅相关资料)。 
    (2)关于数字组合的问题,也可以使用穷举法,先列出方程 
       w1*a+ w2*b+ w3*c+ w4*d = 40( w1,w2,w3,w4属于{-1, 0 ,1} )
      这个方程很好理解,每块砝码可以不放,参数为0,;放在右边参数为1(左物右码),放在左边为-1.
      下面是穷举法代码:
     int w1, w2, w3, w4;

     int weight;
     for (w1=-1; w1<=1; w1+=1)
          for (w2=-1; w2<=1; w2+=1)
               for (w3=-1; w3<=1; w3+=1)
               {
                        if (w1*a+w2*b+w3*c+w4*d == weight)    //weight为1-40之间任意整数
                         {

                              printf("The four pieces'weight are %d %d %d %d\n",a, b, c, d);

                              return 0;

                         }

               }

5.下面是完整的C语言程序
     http://download.csdn.net/my 之破碎的砝码问题源码

6.总结
     通过这个有趣的数学问题,我们可以学到很多东西,当然除了机灵的数学逻辑分析之外,我们对枚举的用法是不是又深入了一些了呢? 





0 0
原创粉丝点击