数据结构分治算法求解假硬币问题

Posted 王超元

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数据结构分治算法求解假硬币问题相关的知识,希望对你有一定的参考价值。

问题描述:

概念 
分治算法的基本思想是将一个大的复杂的问题分解成多个小的、容易解决的问题,通过解决这些小问题进而解决这个大问题。

使用分治算法需要待求解问题能够简化为若干个小规模的相同的问题,通过逐步划分,达到一个易于求解的阶段,而直接进行求解,在程序中可以使用递归方法来进行求解。 
哈哈,说起来很抽象,举个例子就好理解了。

一个袋子里有n个硬币,其中一枚是假币,并且假币和真币一模一样,仅凭肉眼无法区分,仅知道假币比真币轻一些,请问如何查找到假币?

分治算法:

我们可以这样做:

将这n个硬币分成两等份,然后放到天平的两端,则假币在较轻的那一端;

然后将较轻的那一端的硬币再分成2等份,然后再放到天平的两端进行比较,假币还是在较轻的那一段;

直到最后只剩下两个硬币了,分别放到天平的两端,轻的哪一个就是假币。

当然,最后也可能剩下3个硬币,我们可以将这3个硬币中任意拿出来一个,然后将剩下的两个放到天平的两端,如果天平是平的,则说明拿出来的那个硬币就是假币;

如果天平不是平的,则轻的那一端是假币。

代码实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
#include<iostream>
#include<cstdio>
#include<cctype>
#define MAXNUM 30
using namespace std;
int FalseCoin(int coin[], int low, int high){
    int sum1, sum2, sum3;
    int re;
    sum1=sum2=sum3=0;
    if(low+1==high){
        if(coin[low]<coin[high]){
            re=low+1;
            return re;
        }
        else{
            re=high+1;
            return re;
        }
    }
    if((high-low+1)%2==0){
        for(int i=low; i<=low+(high-low)/2; i++){
            sum1=sum1+coin[i];
        }
        for(int i=low+(high-low)/2+1; i<=high; i++){
            sum2=sum2+coin[i];
        }
        if(sum1>sum2){
            re=FalseCoin(coin, low+(high-low)/2+1, high);
            return re;
        }
        else if(sum1<sum2){
            re=FalseCoin(coin, low, low+(high-low)/2);
            return re;
        }
        else{
        }
    }
    else{
        for(int i=low; i<=low+(high-low)/2-1; i++){
            sum1=sum1+coin[i];
        }
        for(int i=low+(high-low)/2+1; i<=high; i++){
            sum2=sum2+coin[i];
        }
        sum3=coin[low+(high-low)/2];
        if(sum1>sum2){
            re=FalseCoin(coin, low+(high-low)/2+1, high);
            return re;
        }
        else{
        }
        if(sum1+sum3==sum2+sum3){
            re=low+(high-low)/2+1;
            return re;
        }
    }
}
int main(){
    int coin[MAXNUM];
    int i,n;
    int locate;
    cout<<"分治算法求解假硬币问题!\\n";
    cout<<"请输入硬币总数目: ";
    cin>>n;
    cout<<"请输入硬币的真假:";
    for(i=0; i<n; i++){
        cin>>coin[i];
    }
    locate=FalseCoin(coin, 0, n-1);
    cout<<"在上述"<<n<<" 个硬币中,第"<<locate<<"个硬币是假的!"<<endl;
    return 0;
}

执行结果:

以上是关于数据结构分治算法求解假硬币问题的主要内容,如果未能解决你的问题,请参考以下文章

数据结构与算法(12)—分治策略

数据结构与算法之深入解析“排列硬币”的求解思路与算法示例

分治算法求解循环赛问题

数据结构与算法之深入解析“零钱兑换”的求解思路与算法示例

算法准备-分治算法解决众数求解问题

有16个一元硬币,其中有个是假的,设计个最简单的办法找出那个假的,最好用到折半查找法。