减治法应用--假币问题实验

1. 实验内容

1)减治法应用实现
在n枚外观相同的硬币中,有一枚是假币,并且已知假币与真币的重量不同,但不知道假币与真币相比较轻还是较重。可以通过一架天平来任意比较两组硬币,设计一个高效的减治算法来检测出这枚假币。
int nCoin(int coin[], int n, int p, int q);
coin[]数组存储各枚硬币的重量。

2.算法分析

在假币问题中,每次用天平比较后,只需解决一个规模减半的问题,所以,它属于一个减治算法。解决这个问题的最自然的想法就是一分为二,也就是把n枚硬币分成两组A、B,每组有[n/2]枚硬币,如果n为奇数,就留下一枚硬币C,然后把两组硬币分别放到天平的两端。如果两组硬币的重量相同,那么留下来的硬币C就是假币;否则,假币就出现在和[n/2]*C重量不相等的一组里,重复上述过程直至找到假币。

2.1 算法的改进

考虑不是把硬币分成两组,而是分成三组,前两组有[n/3]枚硬币A和B,其余的硬币作为第三组C,将前两组硬币放入天平比较。如果他们的重量相同,那么假币一定在第三组C中,用同样的方法对第三组C进行处理;如果前两组的重量不相等,那假币就出现在和(C/ (n-[n/3]*2))*n/3重量不相等的一组里,重复上述过程直至找到假币。在这里插入图片描述
在这里插入图片描述

2.2 伪代码

在这里插入图片描述

2.3 算法实现

在这里插入图片描述
在这里插入图片描述

3. 实验过程

3.1代码:

1.假币的随机生成

void random(int coin[]){
    for (int i = 0; i < N; i++)
        coin[i] =1;        //所有硬币的重量为1
    
    int  x = rand()%N; //生成0到n的随机数
    cout<<"经过random函数赋值,第"<<x+1<<"枚硬币为假币"<<endl;
    coin[x] = 2;  //第x枚硬币为假币
}

2.假币函数

int Coin(int low,int high,int n,int a[]){
    cout<<" low: "<<low<<" high: "<<high<<" n:"<<n<<endl;
    int i,num1,num2,num3;
    int add1=0,add2=0;
    if(n==0)
        return 0;
    if(n==1)
        return low+1;
    if(n%3==0)
        num1=num2=n/3;
    else
        num1=num2=n/3+1;
    num3=n-num1-num2;
    for(i=0;i<num1;i++)
        add1=add1+a[low+i];
    for(i=num1;i<num1+num2;i++)
        add2=add2+a[low+i];
    if(add1>add2)//题目假设,假币是比真币重所以add1重假币在低区间。
        return Coin(low, low+num1-1, num1, a);
    else if(add1<add2)
        return Coin(low+num1, low+num1+num2-1, num2, a);
    else
        return Coin(low+num1+num2, high, num3, a);
    
    
}

3.main函数

#include <iostream>
using namespace std;
const int N=8;
int coin[N];
int main(int argc, const char * argv[]) {
   random(coin);
     cout<<"经过random函数赋值,Coin数组如下"<<endl;
    for (int i = 0; i < N; i++)
        cout<<coin[i]<<" ";        //所有硬币的重量为1
    cout<<endl;
   int x= Coin(0,N-1,N,coin);
   cout<<"经过Coin函数计算,第"<<x<<"为假币"<<endl;
    return 0;
}


4.合起来

#include <iostream>
using namespace std;
const int N=8;
int coin[N];
void random(int coin[]){
    for (int i = 0; i < N; i++)
        coin[i] =1;        //所有硬币的重量为1
    
    int  x = rand()%N; //生成0到n的随机数
    cout<<"经过random函数赋值,第"<<x+1<<"枚硬币为假币"<<endl;
    coin[x] = 2;  //第x枚硬币为假币
}
int Coin(int low,int high,int n,int a[]){
    cout<<" low: "<<low<<" high: "<<high<<" n:"<<n<<endl;
    int i,num1,num2,num3;
    int add1=0,add2=0;
    if(n==0)
        return 0;
    if(n==1)
        return low+1;
    if(n%3==0)
        num1=num2=n/3;
    else
        num1=num2=n/3+1;
    num3=n-num1-num2;
    for(i=0;i<num1;i++)
        add1=add1+a[low+i];
    for(i=num1;i<num1+num2;i++)
        add2=add2+a[low+i];
    if(add1>add2)//题目假设,假币是比真币重所以add1重假币在低区间。
        return Coin(low, low+num1-1, num1, a);
    else if(add1<add2)
        return Coin(low+num1, low+num1+num2-1, num2, a);
    else
        return Coin(low+num1+num2, high, num3, a);
    
    
}
int main(int argc, const char * argv[]) {
   random(coin);
     cout<<"经过random函数赋值,Coin数组如下"<<endl;
    for (int i = 0; i < N; i++)
        cout<<coin[i]<<" ";        //所有硬币的重量为1
    cout<<endl;
   int x= Coin(0,N-1,N,coin);
   cout<<"经过Coin函数计算,第"<<x<<"为假币"<<endl;
    return 0;
}


3.2 结果截图

在这里插入图片描述


版权声明:本文为weixin_43744883原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。