zoukankan      html  css  js  c++  java
  • n枚硬币问题(找假币)

    问题描述:

    在n枚外观相同的硬币中,有一枚是假币,并且已知假币与真币的重量不同,但不知道假币与真币相比较轻还是较重。可以通过一架天平来任意比较两组硬币,设计一个高效的算法来检测这枚假币。

    解题思路:

        使用减治法的解题思路,将硬币分为3堆,则每堆的硬币数量为 n/3 ,但是这是在 n%3==0 的情况下才能成立,所以我们将 n 枚硬币分为 3 堆加 1 堆 余数堆(余数堆可能为0),则可分为如下(n-n%3)/3,  (n-n%3)/3,  (n-n%3)/3,    n%3.

    如下图:

    (n-n%3)/3
    (n-n%3)/3
    (n-n%3)/3
    n%3
    a
    b
    c
    d
    1. 首先获取真币,通过从数组中随机取三枚硬币,互相比较,相等的两枚为真币,任意取一枚作为真币 记录 数组下标
    2. 判断n中的硬币数量,如果n>2则执行3,否则执行5.
    3. 将n分为上图的四堆,拿 a 和 b 比较,如果 a == b ,则 假币在 c 或 d 中。否则假币在 a 或 b 中。
    4. 如果 a == b,则拿 a 和 c 比较。如果 a == c,则假币在d中。将 d 再次 执行本流程。如果不等,则假币在 c 中,将 d (余数堆) 再次 执行流程,并且n=n%3,。
    5. 如果 a != b,则拿 a 和 c 比较。如果 a == c,则假币在b中。将 b 再次 执行本流程。如果不等,则假币在 a 中,将 a 再次 执行流程  2,并且n=(n-n%3)/3。
    6. 如果n==2,则将两枚硬币与真的硬币(通过 数组下标 )进行比较,不同的为假币,输出结果,结束。
    7. 如果n==1,则该硬币就是假币,输出结果结束。

      *注:按照2-5流程分堆下去,在最后一执行流程 2 时,n中含有假币,并且n只可能为1或2.(初始时,n>3,若n<3,则不能判断真假)

    主要代码如下:

     1 //计算硬币总重量
     2  int sum_coin(int coin[],int m,int n){
     3      int result=0;
     4      if(m>n)
     5          return 0;
     6      for(int i=m;i<=n;i++){
     7          result+=coin[i];
     8      }
     9 
    10      return result;
    11  };
    12 
    13 
    14  //找出假币   m , n 数组下标,coin 硬币数组,relCoin 真币数组下标
    15  int check_coin(int coin[],int m,int n,int& relCoin){
    16 
    17         int vary=n-m+1;
    18 
    19         int restCoin=vary%3;
    20         int vary2=vary-restCoin;
    21 
    22         if(vary==1)
    23             return m;
    24 
    25         if(vary==2)
    26         {
    27             if(sum_coin(coin,m,m)==sum_coin(coin,relCoin,relCoin))
    28                 return n;
    29             else
    30                 return m;
    31 
    32         }
    33 
    34 
    35         if(sum_coin(coin,m,m+vary2/3-1)==sum_coin(coin,m+vary2/3,m+(vary2/3)*2-1))//第一堆 == 第二堆
    36         {
    37             if( (sum_coin(coin,m,m+vary2/3-1)==sum_coin(coin,m+(vary2/3)*2,m+vary2-1)))//第一堆 == 第三堆
    38                 check_coin(coin,n-restCoin+1,n,relCoin);
    39             else//第一堆 != 第三堆
    40                 check_coin(coin,m+(vary2/3)*2,m+vary2-1,relCoin);
    41         }
    42         else//第一堆 != 第二堆
    43         {
    44             if(sum_coin(coin,m,m+vary2/3-1)==sum_coin(coin,m+(vary2/3)*2,m+vary2-1))//第一堆 == 第三堆
    45                 check_coin(coin,m+vary2/3,m+(vary2/3)*2-1,relCoin);
    46             else//第一堆 != 第三堆
    47                 check_coin(coin,m,m+vary2/3-1,relCoin);
    48         }
    49 
    50  };
    51 
    52 
    53  //返回真币数组下标
    54  int getRelCoin(int coin[],int m,int n)
    55  {
    56      if(n-m+1<=2)
    57      {
    58          cout<<"硬币数小于3枚!!!无解";
    59         return -1;
    60      }
    61      else
    62      {
    63          if(coin[0]==coin[1])
    64          {
    65              return 0;
    66          }
    67          else
    68          {
    69              if(coin[0]==coin[2])
    70                  return 2;
    71              else
    72              {
    73                  return 1;
    74              }
    75          }
    76      }
    77 
    78  };
    原创,转载请注明来源,默@语:www.h-five.com
  • 相关阅读:
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    如何在一个类中定义一些常量,每个对象都可以方便访问这些常量而不用重新构造?
    __init__函数一定需要吗
    python 面向对象编程
    Linux 操作系统原理 — mmap() 进程虚拟内存映射
    在VSCode中刷leetcode
    MIMO 天线技术
  • 原文地址:https://www.cnblogs.com/hlere/p/5036106.html
Copyright © 2011-2022 走看看