我的八枚硬币问题

实验项目3———8枚硬币问题

1.问题分析:

这个问题就是要找出这八枚硬币中放入假币,前提是还不知道是偏重还是偏轻,所有,要设计一个高效的算法找出这么假币,并且得知是偏重还是偏轻。
假定输入的八枚硬币:a、b、c、d、e、f、g、h
把硬币分成三组,从八枚硬币中任取六枚a、b、c、d、e、f,在天平两端各放三枚进行比较。 假设a、b、c三枚放在天平的一端,d、e、f三枚放在天平的另一端,可能出现如图所示的三种比较结果。

2. 算法设计思路--伪代码emmmmm----写给自己看的,不会写伪代码,随便写的

输入:硬币的重量
输出:假币所在的位置以及偏轻还是偏重
1.如果abc的重量大于def的重量,就移开cf,交换be的位置
    1.如果ae的重量大于db的重量,比较a,d和g币的重量,并且输出
    2.如果ae的重量等于db的重量,比较cf和g币的重量,并且输出
    3.如果ae的重量小于db的重量,比较eb和g币的重量,并且输出
2. 如果abc的重量等于def的重量, 比较gh和a币的重量,并且输出
3. 如果abc的重量小于def的重量,同步骤1.

4.算法结束

3. 算法实现

程序源代码:

#include<iostream>

using namespace std;

void Findout(int v[]);//在八枚硬币中查找

void cmp(int a,int b,int real,int index1,int index2);//将两枚硬币和真硬币比较,找出其中的假硬币

void Outcome(int fal,int tru,int i);//打印数据


int main()

{

    int i,v[9];

    cout<<"请依次输入硬币的重量:"<<endl;

    for(i=1;i<=8;i++)

        cin>>v[i];

    Findout(v);

    return 0;


}

void Findout(int v[])

{

    int a=v[1];

    int b=v[2];

    int c=v[3];

    int d=v[4];

    int e=v[5];

    int f=v[6];

    int g=v[7];

    int h=v[8];

    int abc = a+b+c;

    int def = d+e+f;

    if(abc>def)

    {

        if((a+e) > (d+b))

        {

            cmp(a,d,g,2,4);

        }

        else if((a+e) == (d+b))

        {

            cmp(c,f,g,3,6);

        }

        else

        {

            cmp(b,e,g,2,5);

        }

    }

    else if(abc == def)

    {


        if(g == a)

        {

            Outcome(h,g,8);

        }

        else

        {

            Outcome(g,h,7);

        }

    }

    else

    {

         if((a + e) > (d + b))

        {

            cmp(b,e,g,2,5);

        }

        else if((a + e) == (d + b))

        {

            cmp(c,f,g,3,6);

        }

        else

        {

           cmp(a, d, g,2,4);

        }

    }


}


void Outcome(int fal,int tru,int i)

{

    cout<<"该假币的位置在: "<<i<<endl;

    if(fal > tru) cout<<"该假币的重量偏重!"<<endl;

    else cout<<"该假币的重量偏轻 !"<<endl;

}


void cmp(int a,int b,int real,int index1,int index2)

{

    if(a == real) Outcome(b,real,index2);

    else Outcome(a,real,index1);

}

4. 运行结果(截图)

5. 算法分析

在这个八枚硬币问题中,应用减治法,将问题一分为二,这样只需要3次比较便能解决问题。对于n枚硬币问题,同样可以用减治法处理,采用分治和递归的方法逐步接近问题的解。

6. 经验归纳与总结

减治法是把一个大问题划分为若干个小问题,但是这些子问题不需要分别 ,只需要求解其中的一个子问题,因而也无须对子问题的解进行合并,这样大大提高了算法的效率。

实验扩展:
扩展算法, 使之能处理n 枚硬币中有1 枚假币的问题。

解题思维:将硬币分成A、B、C三组,如果A等于C,则假币在B组,递归将B三等分,重复上述步骤;如果A不等于C,则假币在A和C中,分别将A和B、C和B比较,哪个不等于B,则假币必在其中,递归将其三等分,重复上述步骤。注意,当分组里的硬币数少于3个时,无须划分,直接将组里某个硬币与组外任一硬币比较,不同即是假币,相同的话说明另外一个必是假币。
 

代码如下:---------硬币数量可以根据 Maxnum 的值修改   

     #include <iostream>

using namespace std;

#define Maxnum  9




int Out(int arr[],int low,int high)

{

    int sum = 0;

    for(int i = low; i<=high; i++)

        sum += arr[i];

    return sum;

}


int nCoin(int v[], int n, int low, int high)

{

    int k = n/3;

    int Remain = n%3;

    if(Remain == 0)   //恰好分成了三组

    {

        int index = 0;

        int A = Out(v,low,low+k-1);

        int B = Out(v,low+k,low+2*k-1);

        int C = Out(v,low+2*k,high);

        if(n == 3)//只有三枚硬币的情况

        {

            if(A==B) index = high;

            if(A==C) index = high-1;

            if(B==C) index = low;

            return index;

        }

        else

        {

            if(A==B)

            {

                index = nCoin(v,k,low+2*k,high);//递归调用,从C组中找出假币

                return index;

            }

            if(A==C)

            {

                index = nCoin(v,k,low+k,low+2*k-1);

                return index;

            }

            if(B==C)

            {

                index = nCoin(v,k,low,k-1);

                return index;

            }

        }

    }



    if(Remain == 1)                                          //第三组剩下一枚硬币的情况

    {

        //把最后一个去掉,比较。

        int index = high;

        int A,B,C;


        if(n==1)

            return index;


        else

        {

            A = Out(v,low,low+k-1);

            B = Out(v,low+k,low+2*k-1);

            C = Out(v,low+2*k,high-1);


            //cout<<A<<B<<C<<endl;


            if(A == B && B == C)

            {

                return index;

            }

            else if(A==B)

            {

                cout<<"ramain1 aaaabbb"<<endl;

                index = nCoin(v,k,low+2*k,high-1);

                return index;

            }

            else if(A==C)

            {

                cout<<"ramain1 aaaaccc"<<endl;

                index = nCoin(v,k,low+k,low+2*k-1);

                return index;

            }

            else if(B==C)

            {

                cout<<"ramain1 bbbccc"<<endl;

                index = nCoin(v,k,low,k-1);

                return index;

            }

        }

    }


    if(Remain == 2)                                        余数为2的情况!

    {

        int index = 0;

        int index1 = high-1;

        int index2 = high;

        int A,B,C;

        A = Out(v,low,low+k-1);

        B = Out(v,low+k,low+2*k-1);

        C = Out(v,low+2*k,high-2);

        //cout<<A<<B<<C<<endl;

        if(n<3)

        {

            int campare11 ;

            if(high != Maxnum-1)

                campare11 = v[Maxnum-1];

            else

                campare11 = v[0];

            if(v[high] == campare11)

                index = low;

            if(v[low] == campare11)

                index = high;

            return index;

        }


        else

        {

            if(A==B&&B==C)

            {

                int cam = v[0];

                if(v[high-1] == cam)

                    index = index2;

                if(v[high] == cam)

                    index = index1;

                return index;

            }

            else if(A==B)

            {

                cout<<"ramain2 aaaabbb"<<endl;

                index = nCoin(v,k,low+2*k,high-2);

                return index;

            }

            else if(A==C)

            {

                cout<<"ramain2 aaaacccc"<<endl;

                index = nCoin(v,k,low+k,low+2*k-1);

                return index;

            }

            else if(B==C)

            {

                cout<<"ramain2 bbbccc"<<endl;

                index = nCoin(v,k,low,k-1);

                return index;

            }

        }

    }

}


int main()

{

    int number;

    int v[Maxnum];

    cout<<"请输入硬币的重量:";

    for(int i=0;i<Maxnum;i++)

    {

        cin>>v[i];

    }

    if(Maxnum<3)

    {

        cout<<"数量太少,无法比较"<<endl;

        return 0;

    }

    number  = nCoin(v, Maxnum, 0, Maxnum-1);

    int flag;

    if(number!= Maxnum-1)

        flag = v[Maxnum-1];

    else

        flag = v[0];

    if(v[number] < flag)

        cout<<"假币的位置为 "<<number+1<<"  并且假币偏轻"<<endl;

    else

        cout<<"假币的位置为 "<<number+1<<"  并且假币偏重"<<endl;

    return 0;

} 

运行截图如下:

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值