天平秤重问题

13 篇文章 0 订阅

[前言]

   JSOI(江苏省信息学奥林匹克)2008春季函授B组第一讲中,谈到砝码称重跟三进制对应的问题,参考程序用枚举的方法将1-121这121种称法列举出来:

  用质量为1,3,9,27和81的五种砝码各1个(假如单位为克)称物体的质量,最大可称121,在实验室我们一般要求“物左砝右”。如果砝码允许放在天平的两边,编程输出称不同质量(1~121)物体时,砝码应该怎样安排?

例如要称一个m=14克的物体,我们知道14=27-9-3-1,即14+9+3+1=27。所以我们可以把天平一端放置该物和9、3、1的砝码,而另一端放27的砝码,这样即可称出。

[问题分析]

被称物体的质量计算的数学原理:设被称物体m放在天平左边,根据天平平衡原理,左边质量应等于右边质量。问题关键在于算法中如何体现砝码放在天平左边、右边或没有参加称量。这里可以用-1、1、0表示砝码放在天平左、右和没有参加称量,再没有其它数,所以称为三进制数,每个砝码都有这样的三种状态。被称物体质量计算为:m = a*81 + b*27 + c*9 + d*3 + e。这里a,b,c,d,e分别表示81,27,9,3,1克的砝码是放在天平的左边、右边或是没用。

[参考程序]

Program  ex3(input,output);

var  a,b,c,d,e,m:integer;

Begin

  for  m:=1  to  121   do

    for  a:= 0   to   1  do

      for  b:= -1  to  1  do

        for  c:= -1  to  1  do

          for  d:=  -1  to  1  do

            for  e:=  -1  to  1   do

              if   m = a*81+b*27+c*9+d*3+e   then

                begin

                  write(m,'=',a*81);

                  if b<0 then write(b*27) else write('+',b*27);

                  if c<0 then write(c*9) else write('+',c*9);

                  if d<0 then write(d*3) else write('+',d*3);

                  if e<0 then writeln(e) else writeln('+',e);

                end;

   readln

End.

       许多同学虽然看懂了此程序,却没有真正理解称法与三进制的对应关系,现将五六年我编写的中级讲义中有关内容整理出来,希望能让B组同学真正理解此算法。

[正文]

天平秤重问题

[问题描述]:

有一只天平和N只砝码,如何设计这N只砝码,才能使这天平能够连续秤出的重量最大?假设砝码的最小单位为1克,秤物时物品放在天平的左边,砝码可以放在右边也可以放在左边,不管放在哪一边只要天平能够平衡就行,物品的重量应是右边砝码总重量减去左边砝码的重量。

    输入一个物品的重量,输出其秤重方案。

[分析与算法选择]:

这个问题是从一个经典的数学问题变化而来,这个数学问题的大意是:一个物体重40磅,掉在地上后摔成四片,这四片恰好能够作为砝码连续秤出40磅以内的物品的重量,这四片的重量如何?

(1)如何设计砝码?

我们先不去看单位,直接用数字来描述。因为要能连续秤出一范围内的值,所以首先要有1,从数学上可以知道,N只砝码本身最大能秤的总重就是这N只砝码的重量和,下面就看如何保证连续的数都能秤出了。设这N只砝码的重量分别为W1、W2……Wn,且有W1<=W2<=……<=Wn, W1=1,下面看W2如何设计。

如果W2=1,1、2都能秤出;如果W2=2,1、2、3都能秤出;如果W2=3,1可以秤出(W1)、2可以秤出(W2-W1)、3可以秤出(W2)、4也可以秤出(W1+W2);如果W2=4,则2不能秤出;所以W2最大为3(=3*W1)。

同理可推出W3最大为9(=3*W2);

……

Wn最大为3n-1(=3*Wn-1)。

设计方案为这N只砝码重分别为:1、3、9、27、……、3n-1

(2)如何根据物品重量得到秤重方案?

                    

                      物品(+砝码)         砝码

 

 


 

 因为物品固定放在一连(如左边),只要考虑砝码放的情况。任一个砝码都可能有三种状态:一是跟被秤物品放在一起(如左边),二是不放,三是放在物品另一边(如右边)。最后物品的重量等于所有砝码乘上相应系数的和。这个系数可能是:-1、0、1。

先来看3只砝码时各种重量的称法,如下表所示,其中-1表示砝码放在物品一边、0表示砝码不放进天平、1表示砝码放在物品另一边,如果每一位加1后便只会是0、1、2这3个数字中的一个,所以可以方便地跟三进制数对应起来:

物品重量

3只砝码

每一位加1

9

3

1

三进制数

十进制数

1

0

0

1

112

14(=1+13)

2

0

1

-1

120

15(=2+13)

3

0

1

0

121

16(=3+13)

4

0

1

1

122

17(=4+13)

5

1

-1

-1

200

18(=5+13)

6

1

-1

0

201

19(=6+13)

7

1

-1

1

202

20(=7+13)

8

1

0

-1

210

21(=8+13)

9

1

0

0

211

22(=9+13)

10

1

0

1

212

23(=10+13)

11

1

1

-1

220

24(=11+13)

12

1

1

0

221

25(=12+13)

13

1

1

1

222

26(=13+13)

 

由上表我们可以总结出这样的计算方法:对于给定的物品重量,先确定它最多用到多大的砝码,假定是3n-1,那么先将这个物品的重量加上1、3、……3n-1,得到一个数,再对这个数进行除3取余运算,当余数为0时表示相应的砝码跟物品放在一起,余数为1时表示相应的砝码不放,为2时表示放在物品的另一边。

[程序清单]:

program example12_3;

const max=10;

var w:array[1..max] of integer;

    i,n,m,weight:integer;

begin

 writeln('Poise  is 1,3,9,27,81.....');

 write('Enter goods weight:');readln(weight);

 m:=1; i:=1;

w[i]:=1; {至少要有为1的砝码}

 while m<weight do  {计算最大要多重的砝码w[I]及砝码总重量m}

begin i:=i+1;w[i]:=w[i-1]*3;m:=m+w[i];end;

 n:=weight+m;  i:=1;

 write(weight,'=');

 while n>0 do

  begin

    case n mod 3 of

     0:write('-',w[i]); {为0时砝码跟物体放在一起,计算物体重量时为减}

     2:write('+',w[i]); {为2时砝码单独放,计算物体重量时为加}

    end;

    n:=n div 3; i:=i+1;

   end;

  writeln;

end.

[运行示例]1:

Poise  is 1,3,9,27,81.....

Enter goods weight:85

85=+1+3+81

[运行示例]2:

Poise  is 1,3,9,27,81.....

Enter goods weight:86

86=-1-3+9+81

[运行示例]3:

Poise  is 1,3,9,27,81.....

Enter goods weight:123

123=-3-9-27-81+243

 

[小结]:

对于有任意一检查对象都有多种可能的情况,且总数是固定的,如有N种(n>=2),不妨考虑使用N进制来进行处理,这样会使问题简化许多,一方面可以考虑全面,另一方面这种一一对应关系更加方便通过循环来控制使用数组。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值