• HNU 13073 Ternarian Weights 解题报告


    本题大意

    用天平对一物品进行称重,现有重量不同的砝码,砝码的重量分别为:1,3,9,27,..,3^n。(n<20)

    天平的右侧放砝码,左侧放物品或物品和砝码,使得左右两边的重量相等。

    现有一个物品,计算左右两边应当分别放多少个多大的砝码才能使得天平平衡。

    例如:现在有一个重量为21的物品,当左侧放物品和重量为9的砝码,右边放重量为27和3的砝码时,天平平衡。

    Sample Input
    4
    2
    3
    21
    250
    Sample Output
    left pan: 1
    right pan: 3
    
    left pan:
    right pan: 3
    
    left pan: 9
    right pan: 27 3
    
    left pan: 3
    right pan: 243 9 1

    解题思路

    1、首先计算3^i(0<=i<20),然后将计算结果保存至数组st[],数组add[i]=st[0]+st[1]+st[2]+..+st[i]。

    2、创建两个数组,left[]保存左侧需要添加的砝码,right[]保存右侧需要删除得砝码。

    3、获得大于物品重量的最小add[i]。这是右侧需要的最多得砝码数。

    4、计算右侧砝码数与物品重量之差。并找出小于重量之差的最大砝码。

    5、如果天平右侧已经没有上一步找出的最大砝码,则在天平的左侧添加此砝码,否则,删除天平右侧中上一步找出得最大砝码。

    6、此时,如果天平平衡则退出,若不平衡,则将天平两端的重量之差减去上一步添加或删除的砝码。然后返回第4步。

    具体代码如下:

    #include <stdio.h>
    #include <string.h>
    #define MAX 1000000009
    //st[i]=3^i, add[i]=st[0]+st[1]++st[i];
    long st[20], add[20];
    void init()
    {
        int i;
        st[0] = 1;
        add[0] = 1;
        for(i=1; i<20; i++)
        {
            st[i] = st[i-1]*3;
            add[i] = add[i-1]+st[i];
        }
    }
    int find(int v)        //在st数组中,找出小于V的最大数
    {
        int i;
        for(i=0; i<20; i++)
            if(v < st[i])
                return i-1;
    }
    int main()
    {
        int n, i, hel, tmp, num, num1, num2;
        long left[20],right[20];
        long w;
        init();
        scanf("%d",&n);
        while(n--)
        {
            memset(left,0,sizeof(left));
            memset(right, 0, sizeof(right));
    
            scanf("%ld",&w);
            for(i=0; i<20; i++)
            {
                if(w < add[i])
                    break;
            }
            num = i;
            num1=0;        //左边砝码得个数
            num2=i;        //右边砝码得个数
            hel = add[i]-w;
            while(hel != 0)        //hel==0时, 两端平衡
            {
                //if(hel == 1)
                    //break;
    
                tmp = find(hel);    //找出小于hel的最大砝码
                if(right[tmp] != 0)    //右边已删除此砝码
                {
                    left[tmp] = st[tmp];
                    hel = hel-left[tmp];
                    num1++;
                }
                else
                {
                    right[tmp] = st[tmp];
                    hel = hel-right[tmp];
                    num2--;
                }
            }
        //    if(hel == 1 && right[0])
        //    if(hel != 0)
        //    {
        //        left[0] = hel;
        //    }
            printf("left pan:");
            for(i=num; i>=0; i--)
            {
                if(left[i] != 0)
                    printf(" %ld",left[i]);
            }
            printf("
    right pan:");
            for(i=num; i>=0; i--)
            {
                if(right[i] == 0)
                    printf(" %ld",st[i]);
            }
            printf("
    
    ");
        }
        return 0;
    }




  • 相关阅读:
    HDU 6430 Problem E. TeaTree(虚树)
    hdu6437 Problem L.Videos(网络流)
    Rikka with Prefix Sum(组合数学)
    借教室
    2018年全国多校算法寒假训练营练习比赛(第五场)H Tree Recovery
    1296 营业额统计
    FZU oj Problem 2082 过路费
    大数乘法(适合k进制)
    重载小于号
    莫比乌斯
  • 原文地址:https://www.cnblogs.com/liuwu265/p/4032132.html
Copyright © 2020-2023  润新知