zoukankan      html  css  js  c++  java
  • 假币问题

    Description:

    居然有假币!!! 事情是这样的,现在猪肉涨了,但是农民的工资却不见涨啊,没钱怎么买猪肉啊。老王这就去买猪肉,结果找来的零钱中有假币!!!可惜老王一不小心把它混进了一堆真币里面去了。现在知道假币的重量比真币的质量要轻。给你一个天平,请用最快的时间把那个可恶的假币找出来。

    Input:

    输入有多行,每一行的值为硬币的数目n,1≤n≤2^30,输入0结束程序

    Output:

    最少要称多少次一定能把那个假币找出来。输出对应输入行数。

    Sample Input Copy:

    3

    12

    0

    Sample Output Copy:

    1

    3

    HINT

    示例1中共有3枚硬币,所以任意取2个放天平上称量一下。 因为假币的重量比较轻。 如果天平不平衡,则较轻的那枚就是假币。 如果天平平衡,则说明这两枚硬币都是真的,而剩下那枚是假币。

    题解:假设我们现在只有三枚硬币,那么我们分成三分A , B, C

    1.若 A == B  ,则 C 是假币

    2.若 A < B    ,  则 A 是假币

    3.若A > B     ,  则 B 是假币

    则推出一个结论: f(3) = 1   --- >  继续推广  f( 9 ) = ?

    现在分成 3A, 3B, 3C 三部分

    1.若 3A == 3B ,则在 3C中查找,现在继续把 3C 分成 3 部分 AA, BB , CC 三部分

    (1).若 AA == BB ,则 CC 是假币 

    (2).若 AA <  BB  ,  则 AA  是假币 

    (3).若 AA >  BB  ,  则 BB  是假币

    2.若 3A >   3B  , 则假币在 3B 中查找, 现在继续把 3B  分成 3 部分 AA, BB , CC 三部分

    (1).若 AA == BB ,则 CC 是假币 

    (2).若 AA <  BB  ,  则 AA  是假币 

    (3).若 AA >  BB  ,  则 BB  是假币

    3.若 3A <   3B , 则假币在 3A 中查找, 现在继续把 3A 分成三部分 AA, BB, CC 三部分

    1).若 AA == BB ,则 CC 是假币 

    (2).若 AA <  BB  ,  则 AA  是假币 

    (3).若 AA >  BB  ,  则 BB  是假币

    推出一个结论:f(9) = 2  ----- >  那么我们得出一个结论 f(3^n) = n, f(3^n + 1) = n + 1

    最后我们得出一个结论:我们的结论是:有n(n≥3次,就能找出那个假币。)个硬币,其中一个是假币,假币的重量比其他的要重一些。给一架天平,至少称次,就能找出那个假币。

    分析过程可以画成一棵树,叶子节点顶多只访问一次,然后逐步向下搜索。

    “三分”是整个解法的核心。我们选择三分,而不是二分或者四分是有原因的,它的本质是由判定树的特殊结构——三叉树——所决定的。

    同时还必须注意一点,我们在三分的时候有两个字很讲究:“均匀”。实际上树的深度 ≥ 中的“=”当且仅当硬币被均匀的分配时才能达到。

    这里说的“均匀”是指“在最坏情况下获得最好的效果”。因为一棵树的深度是由它根节点儿子中深度最大的儿子决定的,为了使得整个树深度最小,我们就要务必使得深度最大的儿子深度最小,这就是“均匀”分配的理论根据。

     1 #include <iostream>
     2 #include <cmath>
     3 #include <cstdio>
     4 using namespace std;
     5 
     6 int main()
     7 {
     8     int n;
     9     while(~scanf("%d",&n))
    10     {
    11         if(n == 0) break;
    12         if(n == 1)
    13         {
    14             cout<<"0"<<endl;
    15             continue;
    16         }
    17         int count = 0, flag = 0;
    18         while(n)
    19         {
    20             if(n%3 && n!= 1)
    21                 flag++;
    22             n /= 3;
    23             count++;
    24         }
    25         if(flag == 0)
    26             count--;
    27         cout<<count<<endl;
    28     }
    29     return 0;
    30 }
    永远年轻 永远热泪盈眶!
  • 相关阅读:
    50 系统调用的实现
    49 进程调度预备开发(下)
    48 进程调度预备开发(上)
    47 多进程并行执行(下)
    IIC总线
    46 多进程并行执行(上)
    45 内核中的中断处理(下)
    解决错误/usr/bin/ld: cannot find -lz
    rsync只传输隐藏文件
    Firewall命令
  • 原文地址:https://www.cnblogs.com/Edviv/p/11588555.html
Copyright © 2011-2022 走看看