算法设计与分析基础——假币问题(三分法)

一、算法介绍

有n个金币,其中一个是假币。这个假币的重量比真币的重量要轻一点,所有n-1个金币的重量是一样的。现在有一架天平,设计高效的算法(用最少的使用天平次数)找出那个假的金币。

二、算法思想

每次平均分三堆的结果可能有:余数0 余数1 余数2

  • 余数0: 平均分,任选两堆(堆1+堆2)比较,

如果平衡: 堆3含假币;

如果不平衡: 比较堆1和堆3,

                       如果平衡: 堆2含假币;

                       如果不平衡: 堆1含假币;

  • 余数1: 平均分后得到3堆+1个硬币,任选两堆(堆1+堆2)比较,

如果平衡: 比较堆1和堆3,

                    如果平衡: 剩余的单个硬币为假,

                    如果不平衡: 堆3为含假币的堆

如果不平衡: 比较堆1和堆3,

                      如果平衡: 堆2含假币

                      如果不平衡: 堆1含假币

  • 余数2: 平均分后得到3堆+2个硬币,任选两堆(堆1+堆2)比较,

如果平衡: 比较堆1和堆3

                   如果平衡: 假币在两个单个硬币中,这两个硬币必然是不平衡的,这时从堆中找出任意一枚硬币,从两个单个硬币中拿出硬币1进行比较

                                      如果平衡:假币为币2

                                      如果不平衡:假币为币1

                    如果不平衡: 堆3为含假币的堆

如果不平衡: 比较堆1和堆3

                       如果平衡: 堆2含假币

                       如果不平衡: 堆1含假币

三、实验代码

#include <iostream>
#include <math.h>

using namespace std;

#define numnum 14
int coin[numnum] = {2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3};

/*计算总重量 */
int Weight_Sum(int arr[], int low, int high)
{
    int sum = 0;
    for (int i = low; i <= high; i++)
        sum += arr[i];
    return sum;
}

/* 称硬币,找出假币数组下标*/
int Weight_Coin(int coin[], int coinNum, int low, int high)
{
    int k = floor(coinNum / 3);
    int r = coinNum % 3;
    if (r == 0)
    {
        int index = 0;
        int A, B, C;
        A = Weight_Sum(coin, low, low + k - 1);
        B = Weight_Sum(coin, low + k, low + 2 * k - 1);
        C = Weight_Sum(coin, low + 2 * k, high);

        if (coinNum == 3)
        {
            if (A == B)
            {
                index = high;
            }
            else if (A == C)
            {
                index = high - 1;
            }
            else
            {
                index = low;
            }
            return index;
        }
        else
        {
            if (A == B)
            {
                index = Weight_Coin(coin, k, low + 2 * k, high);
                return index;
            }
            else if (A == C)
            {
                index = Weight_Coin(coin, k, low + k, low + 2 * k - 1);
                return index;
            }
            else
            {
                index = Weight_Coin(coin, k, low, k - 1);
                return index;
            }
        }
    }

    if (r == 1)
    {

        int index = high;
        int A, B, C;
        A = Weight_Sum(coin, low, low + k - 1);
        B = Weight_Sum(coin, low + k, low + 2 * k - 1);
        C = Weight_Sum(coin, low + 2 * k, high - 1);
        if (coinNum == 1)
        {
            return index;
        }
        else
        {

            if (A == B)
            {
                if (A == C)
                    return index;
                if ((A < C || A > C))
                {
                    index = Weight_Coin(coin, k, low + 2 * k, high - 1);
                    return index;
                }
            }
            else if (A == C)
            {
                index = Weight_Coin(coin, k, low + k, low + 2 * k - 1);
                return index;
            }
            else
            {
                index = Weight_Coin(coin, k, low, k - 1);
                return index;
            }
        }
    }
    if (r == 2)
    {
        int index = 0;
        int index1 = high - 1;
        int index2 = high;
        int A, B, C;
        A = Weight_Sum(coin, low, low + k - 1);
        B = Weight_Sum(coin, low + k, low + 2 * k - 1);
        C = Weight_Sum(coin, low + 2 * k, high - 2);
        if (coinNum < 3)
        {
            int campare1; //参照物
            if (high != numnum - 1)
                campare1 = coin[numnum - 1];
            else
                campare1 = coin[0];
            if (coin[high] == campare1)
                index = low;
            if (coin[low] == campare1)
                index = high;
            return index;
        }

        else
        {
            if (A == B && B == C)
            {
                int cam = coin[0];
                if (coin[high - 1] == cam)
                    index = index2;
                if (coin[high] == cam)
                    index = index1;
                return index;
            }
            else if ((A == B) && (A < C || A > C))
            {

                index = Weight_Coin(coin, k, low + 2 * k, high - 2);
                return index;
            }
            else if (A == C)
            {
                index = Weight_Coin(coin, k, low + k, low + 2 * k - 1);
                return index;
            }
            else
            {
                index = Weight_Coin(coin, k, low, k - 1);
                return index;
            }
        }
    }
    return 0;
}
/*判断假币质量*/
void Judge(int number)
{
    int campareble;
    if (number != numnum - 1)
        campareble = coin[numnum - 1];
    else
        campareble = coin[0];
    if (coin[number] < campareble)
        cout << "假币的位置为 " << number << "  并且假币偏轻" << endl;
    else if (coin[number] > campareble)
        cout << "假币的位置为 " << number << "  并且假币偏重" << endl;
    else
        cout << "参照出错" << endl;
}
int main()
{
    if (numnum < 3)
    {
        cout << "数量太少,无法比较" << endl;
        return 0;
    }
    int number;
    number = Weight_Coin(coin, numnum, 0, numnum - 1);
    Judge(number);
    return 0;
}

四、实验结论

1、

2、

3、

参考博文https://blog.csdn.net/ngl158358/article/details/79953769

  • 24
    点赞
  • 183
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值