c語言稱重砝碼

tooooo_young發表於2015-06-09
這個問題確實又是一個三進位制的問題。記得以前我探討過一個稱壞乒乓球的問題,和這個問題有異曲同工之處。
這個問題其實包含三個子問題:

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

相關文章