• 【三分】【AOJ-158】有假币


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

    Input
    1≤n≤2^30,输入0结束程序。
    Output
    最少要称几次一定能把那个假币找出来。
    Sample Input
    3
    12
    0

     
    Sample Output
    1
    3
     
     
    思路:
    三分法

    一、     首先我们先来考虑最简单的问题1。为了方便叙述,把n个硬币按1,2,…,n顺次编号。

    二、     若n=3,把一号硬币放在天平左边、二号硬币放在天平右边。如果天平:

    三、     左偏,一号重,是假币。

    四、     右偏,二号重,是假币。

    五、     保持平衡,那么一、二都是正常的硬币,因此就只有可能三号硬币是假币了。

    六、     因此n=3,至多一次就能称出哪个是假币。记作f(3)=1。

    七、     下面考虑n=9。把所有的硬币分成三组:A{1,2,3},B{4,5,6},C{7,8,9}。A组的硬币放在左边、B组放在右边。如果天平:

    八、     左偏,则假币在A组里面。

    九、     右偏,则假币在B组里面。

    十、     保持平衡,假币在C组里面。

    十一、   无论在哪个组里面,我们已经把假币的范围从“9”缩小到了“3”,也就是减少到原来的1/3。之前我们已经研究过,3个硬币1次就能称出来,故而f(9)=2。

    十二、   不难推广到一般的情况:

    十三、   定理1.1 f(3n)=n。

    十四、   证明:n=1,2时,已证。设n=k成立,则f(3k)=k;下面考虑n=k+1的情况。

    十五、   将3k+1个硬币分成三堆A, B, C,使得|A|=|B|=|C|=3k。把A放在天平左边、B放在右边,天平:

    十六、   左偏,假币在A

    十七、   右偏,假币在B

    十八、   平衡,假币在C

    十九、   无论哪种结果,我们都把假币的范围缩小到了3k个硬币里面。而f(3k)=k,故而f(3k+1)=k+1。

    二十、   综上,定理1.1成立。

    二十一、稍经分析不难得到:

    二十二、定理1.2 f(n)=

    二十三、这个的证明和定理1.1完全类似,分n mod 3 = 0, 1, 2适当讨论即可。

    二十四、我们必须注意到 是可行的,因为我们能够构造出这样一个方案。问题是它是否最优?

    二十五、我们采取的方案是每次将硬币尽量均匀的三分,这样做的根据就是天平只有三种结果:左偏、右偏、平衡。于是就能保证无论假币在哪一份都能将结果的范围缩小到原来的1/3。从感性上认识, 应该就是最优解了。

    二十六、为了更加严格的证明 的最优性,我们引进判定树的概念。

    二十七、下图就是n=9时的一种判定树:

    二十八、此题的判定树是这样一棵树:

    二十九、叶子节点代表一种可能的结果。

    三十、   非叶子节点代表一次称量。

    三十一、非叶子节点至多有三个儿子,分别代表天平的左偏、右偏、平衡三种情况。

    三十二、任意一种称量方案都能唯一的表示成一棵判定树;反过来一棵判定树也唯一对应一种称量方案。

    三十三、容易看出判定树的深度就是称量次数。这就是我们之所以引进它的原因。

    三十四、做出判断之前,谁也无法预知哪个硬币是假币,每个都有可能是我们的目标;因此一个有意义的判定树应该具有至少n个叶子节点。

    三十五、 n个叶子节点的树的深度h ≥ ,故而可以证明,f(n)= 是最优的。

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

    三十七、 具体的方案是将硬币每次都尽量均匀的三分。

    三十八、 让我们总结一下。

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

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

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

     

     

    参考代码

    #include <stdio.h>
    #include <math.h>
    int main()
    {
        long int n;
        int m;
        while(scanf("%ld",&n)&&n)
        {
            m=(int)ceil(log(n*1.0)/log(3.0));//ceil()向上取整函数 log(n)/log(3)用三分法可证
            printf("%d
    ",m);
        }
        return 0;
    }
  • 相关阅读:
    java学习笔记(三)
    JAVA 学习笔记(2)
    java学习笔记
    第二次作业完成情况
    第一次作业完成情况
    使用MarkDown标记语言发博客
    《Java高级程序设计》第一周作业
    纪逝去的毕业后的两年时光
    #这是来联系Markdown语法的
    CodeFirst初体验——问题三
  • 原文地址:https://www.cnblogs.com/ahu-shu/p/3471779.html
Copyright © 2020-2023  润新知