您的位置:首页 > 编程语言 > C语言/C++

c语言称重砝码

2015-06-09 20:45 190 查看
这个问题确实又是一个三进制的问题。记得以前我探讨过一个称坏乒乓球的问题,和这个问题有异曲同工之处。

这个问题其实包含三个子问题:

1.称量需要多少个砝码。

2.每个砝码的质量是多少。

3.称量某一重物,达到平衡状态时,每个砝码如何摆放。

先讨论第1个问题。

不管是天平还是普通杆秤,砝码的放置位置都有三个,一是不放在秤上,二是放在秤上与被称物不在一起,三是放在秤上与被称物在一起。楼主的“标准答案”并没有考虑第三种情况。

我们还是以天平作为衡器来描述问题吧。

我们可以设被称量物总是放在左边的,这样天平的左右盘的意义就不同了。

每个砝码在称量中可以有三种状态。放在左边、不放上天平、放在右边。

那么N个砝码最多可以组合出3^N种状态。这3^N种状态除了全不放上天平外其它状态都有一个对称的状态。

假设有某一状态是左边放了Sa砝码,右边放了Sb砝码(Sa,Sb都是砝码集S的子集,并且Sa、Sb不相交),那么必然会有另一状态(左边放Sb右边放Sa)与之对应。

设左边砝码总重量为Wa,右边为Wb,则这一平衡状态下的被称物重量为Wb - Wa。

与它对称的状态在平衡时被称物重量为Wa - Wb。

很显然,这一对状态下被称物重量必然有一个为负值。负重量在现实中不存在。

所以N个砝码能表示的正状态为(3^N - 1)/2种。也就是能表示的最大的被称物质量。

由此,称量重量为W的重物时需要的砝码数是 N = log3(2 * W + 1)。这是小曹说错的地方。

接下来讨论第2个问题。

有了上面的讨论其实这第2个问题的结论已经出来了。状态呈现三进制计数的性质,所以每个砝码3的幂次,这样即可保证状态无重叠且连续。

从小到大,第i个砝码的质量应该是 3^(i - 1)。

最后讨论第3个问题。

将状态表示成三进制数,每一位对应一个砝码(质量为该位的基)的取值为0、1、2。现在我们建立三进制数与被称量物重量的对应关系。

我们规定0表示该位对应砝码放在左边,1表示不放在天平上,2表示放在右边。

这么规定是有意义的。

我们希望用三进制数的变化情况与被称物质量的变化对应。也就是说被称物质量越大这个三进制数的值也越大。

在这种规定下三进制0的意义是什么?

是所有砝码都放在左边,即与被称量物放在一起。这时如果要天平平衡,那被称量物具有的将是负质量。

而天平上什么都不放的状态(零质量)对应的数值是...1111111。即每位都是1。

所以这里只是应用了部分的三进制计数性质,而非正常意义下的三进制数。

这里的0表示的其实是负无穷,而无限多的1表示的是十进制数0。它其实是将整个整数域映射到了非负整数域。

而我们使用的是有限位三进制数,且最高位为2(略去更高位的无限个1)。

这个概念比较抽象,如果理解不了可以跳过。

由于每位为1表示零质量,而我们用N个砝码。所以我们计算的基准值应为(N^3 - 1) / 2。

对于重量为W的重物,它对应的三进制数值为。

(3^N - 1) / 2 + W

这个三进制值的每一位的值将表示该位对应砝码的放置位置。

#include<stdio.h>
#include<math.h>

int f(int w)

{

    return ceil(log(w *
2 + 1) / log(3));

}

void print_weight(int w)

{

    int n, a;

    const char * B[] = {"L",
"O",
"R"};

    n = f(w);

    for(a = (int)(pow(3, n) -
1) / 2 + w; a; a /=
3)

        printf("%5s
", B[a % 3]);

}

int main()

{

    int w, n, i, t;

    printf("Input weight :
");

    scanf("%d", &w);

    n = f(w);

    printf("It needs %d weights.\n", n);

    printf("Every weights is:\n");

    for(i = 0, t =
1; i < n; i++, t *=
3) printf("%5d
", t);

    puts("");

    print_weight(w);

    return 0;

}

假如现在只有一个1g的砝码,那么我们只能称1g的重量,我们把能称的重量集合记为S, 现在的S1 = {1}。

现在给了我另外一个砝码m(m!=1)克。那我们能称的重量为1, m-1, m , m+1, 若m-1!=1,那么我们就能称4个重量,S2 = {1, m-1, m, m+1},比如说给的m=3,那么我们能称的重量为S2 = {1,2,3,4},很显然,在某个时刻,只能取S中的一个值,若取了1和3相当于取4。即S2 = {S1, m-S1, m, m+S1}.

现在我们有了1g,3g的砝码,那么再给我一个砝码m,我能称的重量最多能有多少个呢?肯定是1,2,3,4,m-4,m-3,m-2,m-1,m,m+1,m+2,m+3,m+4,若m=9,则连续称的重量为S3= {1,2,3,4,5,6,7,8,9,10,11,12,13}。即S3 = {S2,m-S2, m, m+S2}。

不难看出,这里有个规律: 假设手头上有m个砝码,可以称的连续重量为n个,那么再给一个砝码,此砝码重量为2n+1,那么能称的连续重量为3n+1个,即已经能称的1到n的重量,加上新加的砝码2n+1依次减去1到n的重量得到的n+1到2n的n个重量,再加上新加的砝码本身的重量2n+1,再加上2n+1依次加上1到n的重量得到的2n+2到3n+1的n个重量。此时砝码个数为m+1。

m个砝码能称的最多重量为(3^m-1)/2。第m个砝码的重量为3^(m-1)。

文章出处:http://bbs.bccn.net/thread-372721-1-1.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: