砝码称重1

参考 https://blog.csdn.net/linhaiyun_ytdx/article/details/50629743

如果只有5个砝码,重量分别是1,3,9,27,81。已知它们可以组合称出1到121之间任意整数重量(砝码允许放在左右两个盘中)。
本题目要求编程实现:对用户给定的重量,给出砝码组合方案。
例如:
用户输入:
5
程序输出:
9-3-1
用户输入:
19
程序输出:
27-9+1

要求程序输出的组合总是大数在前小数在后。
可以假设用户的输入的数字符合范围1~121。
————————————————
版权声明:本文为CSDN博主「潇潇雨歇_」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/linhaiyun_ytdx/article/details/50629743

查资料的时候,碰到这个问题,索性把所有的砝码相关的算法题都总结一边。下面是自己实现的方案。

最简单的穷举法

    char a[] = { 1, 3, 9, 27, 81 };
    int num = 0;
    cin >> num;
    for (int i0 = -1; i0 < 2; i0++)
    {
        for (int i1 = -1; i1 < 2; i1++)
        {
            for (int i2 = -1; i2 < 2; i2++)
            {
                for (int i3 = -1; i3 < 2; i3++)
                {
                    for (int i4 = -1; i4 < 2; i4++)
                    {
                        if (num == (a[0] * i0 + a[1] * i1 + a[2] * i2 + a[3] * i3 + a[4] * i4))
                        {
                            cout << i0 << i1 << i2 << i3 << i4;
                        }
                    }
                }
            }
        }
    }

把穷举法改成递归

bool test(char* a, int index, int nownum, int num, char* b)
{
    if (index == 5)
    {
        return false;
    }
    int tmp = nownum;
    b[index] = 0;
    if (nownum == num)
    {
        return true;
    }
    else if (test(a, index + 1, nownum, num, b))
    {
        return true;
    }

    b[index] = -1;
    nownum = tmp - a[index];
    if (nownum == num)
    {
        return true;
    }
    else if (test(a, index + 1, nownum, num, b))
    {
        return true;
    }

    b[index] = 1;
    nownum = tmp + a[index];
    if (nownum == num)
    {
        return true;
    }
    else if (test(a, index + 1, nownum, num, b))
    {
        return true;
    }
    b[index] = 0;
    return false;
}

int main()
{
    char a[] = { 1, 3, 9, 27, 81 };
    char b[5] = { 0 };
    int num = 0;
    cin >> num;
    test(a, 0, 0, num, b);
}

这样可以看出重复的计算非常多,那么给定的题目有没有规律呢?参考上面作者的思路,我们发现1只能表示1;1和3呢,最大可以表示到4;1,3,9呢,可以表示到13,就是与斐波那契数列一样相加,得到一个区间,那么在每个区间内,比如如果数字在1和3生成的区间1-4内,肯定是有1和3组成的,并且大于1的数字,肯定需要3.因为都只有一个砝码,不可能砝码a可以称出大于a自己质量的物品。如果是在5-13之间的数字呢?那么就肯定需要9.所以我们先找到最大的数字,然后用输入的数字减去最大的数字,如果是正数,表示还大,再减去第二小的数字;如果是负数,表示小了,就加上下一个数字。放到天平上也是,如果物品是4,那么我们先放一个3,再放一个1.如果是5呢,我们先放一个9,因为1和3都加上也压不起4,所以要更大的9,放了9,天平朝砝码倾斜,表示多了,所以要在物品这边加上砝码,把多余的重量(也就是相减的负值)抵消掉。既然是砝码帮助抵消的重量,所以计算的时候要减去这部分不输入物品的砝码的重量。

int main()
{
    int a[] = { 1, 3, 9, 27, 81 };
    int b[5] = { 0 };
    for (int i = 0; i < 5; i++)
    {
        if (i > 0)
        {
            b[i] = a[i] + b[i - 1];
        }
        else
        {
            b[i] = a[i];
        }
    }
    int num = 0;
    cin >> num;
    while (num != 0)
    {
        int index = 0;
        for (int i = 0; i < 5; i++)
        {
            if (std::abs(num) <= b[i])
            {
                index = i;
                break;
            }
        }
        if (num > 0)
        {
            cout << "+" << a[index];
        }
        else if (num < 0)
        {
            cout << "-" << a[index];
        }
        if (num > 0)
        {
            num = num - a[index];
        }
        else if (num < 0)
        {
            num = num + a[index];
        }
    }
    char inchar;
    cin >> inchar;
}

 

posted @ 2019-12-26 17:53  秋来叶黄  阅读(408)  评论(0编辑  收藏  举报