找坏硬币

问题描述

在n(n>=3)枚硬币中有一枚重量不合格的硬币(过轻或过重),如果只有一架天平可以用来称重且称重的硬币数没有限制,设计一个算法,找出这枚不合格的硬币,使得称重的次数最少(优于O(n))。

(提示:分成n/3或n/4份,至少两份数量相等)

思路

借鉴二分法的思想,不过是分成3堆,其中两堆个数一致,另外一堆可以不一致。不管是奇数还是偶数个硬币,(被3整除最好)都可分成大致相同的3堆,比较两堆一致的,若不相等,说明坏硬币在这两堆中。若相等,说明在第3堆中。重复操作,直到只剩2个硬币。

//Q6   在n(n>=3)枚硬币中有一枚重量不合格的硬币(过轻或过重),如果只有一架天平可以用来称重且称重的硬币数没有限制,
// 设计一个算法,找出这枚不合格的硬币,使得称重的次数最少(优于O(n))。

// 思路: 采用分治策略。如果n<3,那么将拿走的硬币与剩下的硬币比较,不等的是坏币;将n枚硬币分为大致相等的3份,
//如果n(mod 3)≠0,那么令两份少的硬币相等。取两份相等的硬币放到天平上,如果不等,那么这两份硬币中含有坏币,
//否则坏币在第3份中。递归处理,直到n<3为止。

//关键词:硬币 坏 分治coins

//硬币结构体
struct Coin
{
    int weight;
    int label;
    Coin(int weight, int label)// 构造函数
    {
        this->weight = weight;
        this->label = label;
    }
};

int gettotalweight(vector<Coin> coins) {
    int totalweight = 0;
    for (vector<Coin>::iterator iter = coins.begin(); iter != coins.end(); ++iter) {
        totalweight = totalweight+iter->weight;
    }
    return totalweight;
}

#include "algorithm"
int turewight = 0;
int findBadCoin(vector<Coin> coins) {
    int n = coins.size();
    int k = n / 3; // 将硬币分为3堆 个数分别为k,k,n-2k
    vector<Coin> A,B,C;  
    int result = 0;
    A.insert(A.begin(),coins.begin() , coins.begin() + k);
    B.insert(B.begin(),coins.begin() + k, coins.begin() + 2*k );
    C.insert(C.begin(),coins.begin() + 2*k, coins.end());
    if (n == 2)
    {
        coins[0].weight == turewight ? result = coins[1].label : result = coins[0].label;
        return result;
    }
    if(n>3){
        if (gettotalweight(A)!= gettotalweight(B)) { //A与B的重量不相等
            coins.clear();
            coins.insert(coins.begin(), A.begin(), A.end()); // 重新整合A和B的元素到coins中
            coins.insert(coins.end(), B.begin(), B.end());
            turewight = C[0].weight;//记录真实重量方便最后的比较
        }
        else // 坏币在第3堆中
        {
            coins.clear();
            coins.insert(coins.begin(), C.begin(), C.end());
        }      
        return findBadCoin(coins);
    }  
}
//Ques20201004
int main()
{
    //Q1
    //cin >> k;//输入要找的数字c语言把cin换为scanf即可
    //cout << BinarySearch(0, 9);//从数组a[0]到a[9]c语言把cout换为printf即可

    //Q2
    /*int n = 9;
    int arr[] = { -1,3,5,2,7,8,-9,1,-4 };
    
    f(arr,n);*/


    // Q3
 /*   char A = 'A';
    char B = 'B';
    char C = 'C';
    Hanoi(3, A, B, C);*/



    //Q4
   /* int arr[] = { 1,3,5,8,9,7,6,1,2 };
    cout<<siglePeak(arr,0,8);*/


    // Q5
    //int arr[] = { 1,1,2,3,5,7,8,9 };
    //printL_U(arr,1,7,8);// L=1,U=7 数组长度为8

    // Q6
    vector<Coin> coins;
    for (int i = 0; i < 19;i++) {
        
        if (i == 12) {// 坏硬币的重量为2           
            coins.push_back(Coin(2, 12));
        }
        else { // 生成20个硬币
            coins.push_back(Coin(1, i));
        }
    }
    cout<<findBadCoin(coins);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/Toky_min/article/details/108923527