zoukankan      html  css  js  c++  java
  • 记录一些经典的算法

    1、飞机飞行问题

    每个飞机只有一个油箱,飞机之间可以相互加油(注意是相互,没有加油机),一箱油可供一架飞机绕地球飞半圈。

    问:为使至少一架飞机绕地球一圈回到起飞时的飞机场,至少需要出动几架飞机? (所有飞机从同一机场起飞,而且必须安全返回机场,不允许中途降落,中间没有飞机场)

    解答:

    我们把全程划分为多个4分之1段,可以知道,要一架飞机全程需要两箱油,假设飞机A为需要全程的飞机,则在4分之1时油必须满箱,由此考虑过程:

    ABC同时起飞,至8分之1时,C给AB各4分之1的油,剩下4分之1油返回,AB继续飞行到4分之1时,B给A加4分之1油,将A加满,B剩余2分之1油,返回。

    A飞至2分之1时,D反方向起飞,至4分之3时,D给A加4分之1油,E反方向飞,到8分之1的位置,给AD各4分之1的油,ADE同时返回。

    注:此方法为最优解,其余加油方式均不能满足。

     

    2、100层楼扔玻璃球,鸡蛋或者杯子的问题

    某幢大楼有100层。你手里有两颗一模一样的玻璃珠。

    当你拿着玻璃珠在某一层往下扔的时候,一定会有两个结果,玻璃珠碎了或者没碎。这幢大楼有个临界楼层。低于它的楼层,往下扔玻璃珠,玻璃珠不会碎,等于或高于它的楼层,扔下玻璃珠,玻璃珠一定会碎。

    玻璃珠碎了就不能再扔。现在让你设计一种方式,使得在该方式下,最坏的情况扔的次数比其他任何方式最坏的次数都少。也就是设计一种最有效的方式。

    例如:有这样一种方式,第一次选择在60层扔,若碎了,说明临界点在60层及以下楼层,这时只有一颗珠子,剩下的只能是从第一层,一层一层往上实验,最坏的情况,要实验59次,加上之前的第一次,一共60次。

    若没碎,则只要从61层往上试即可,最多只要试40次,加上之前一共需41次。两种情况取最多的那种。故这种方式最坏的情况要试60次。

    那该如何设计方式呢?

    解答:

    首先理解题意,将玻璃珠从某一层楼扔下,如果没碎,我还可以再利用它测试。

    如果碎了的话,就不能再继续用了。
    如果我从x楼扔下,没碎,在x+1楼扔下,碎掉了,即证明找到了x+1是刚好碎掉的楼层。

    问题的关键是,怎么快速找到这个楼层呢?这是一个查找问题。
    我们需要一个策略方法来快速地找到它,就看谁的方法比较优秀。
    而优秀的方法其评价标准显而易见:各种情况下都能快速地找到目标楼层。

    思考路径:
    如果只有一个玻璃珠的话,应该怎么做呢?
    稍微想一下也可以知道,必定只能一层一层地扔,1楼没碎扔2楼,2楼没碎扔3楼,直到碎掉。

    现在我有两个玻璃珠

    学习过算法和程序的人应该都知道二分法,很容易想到这样去做,因为面对的是一个搜索问题。
    所以可能会给出这样的策略:
    从50楼扔下,没碎的话,再扔75楼,再没碎我扔88楼,依次下去很快就可以锁定楼层?
    很快你会意识到问题所在,万一第一次从50层楼扔下去,碎了咋整,难道又一层一层地扔?
    玻璃珠刚好在49层碎掉的话。最差的情况我需要扔50次,这方法不行。

    再一个比较常见的方法是,先分区间的扔,再慢慢地一层一层地扔,隐含着分段查找的策略。

    ===============================================================================================================================
    具体操作方式是:
    先从第10楼扔,再从第20楼扔,依次下去,如果到某一层碎掉,比如50层碎掉了,我再从41楼开始扔,这样的话应该算是比较快了把?
    这个方法是要快一点,不过如果玻璃珠在99楼才会刚好碎掉。这样,最差的情况下,需要扔19次才能找到目标楼层。

    我们需要的方法是玻璃珠不论是在1楼碎,49楼碎,99楼碎都要能快速锁定的方法。

    继续思考刚才方法的缺陷,当玻璃珠质量比较差的时候,此方法还是比较快速的找到的。比如玻璃珠是在19楼刚好碎,我只需要扔11次,比99楼刚好碎的情况要少很多次。

    所以我们的愿望是:
    玻璃珠的质量无论分布在哪个查找区间,都可以快速地找到。所以我们可以“匀”一下刚才的方法。即最开始需要大胆地扔,然后再慢慢小心地扔。

    ===============================================================================================================================

    具体方法设计:
    每次扔的区间减少一层,这样做可以保证每个区间查找的最差次数是一样的。
    假定第一步在15楼扔,没碎的话则下一步在29楼扔,没碎下一步在42楼扔....碎掉之后则在上一次没碎的楼层开始向上扔。那么最开始在哪一层开始扔呢??
    这里我们需要拿支笔算一下:
    x+(x-1)+(x-2)+...+2 >=100
    求解出答案为14。

    即最终给出的解决方案是:
    最开始从14楼开始扔,没碎的话在27楼扔,再没碎的话在39楼扔.....一旦碎掉,则从上一次没碎的楼层逐层往上扔,即可快速确认杯子在哪一层刚好会碎掉。

    3、5赛道25匹马,找最快的5匹的问题

    一共有25匹马,有一个赛场,赛场有5个赛道,就是说最多同时可以有5匹马一起比赛。假设每匹马都跑的很稳定,不用任何其他工具,只通过马与马之间的比赛,试问,最少得比多少场才能知道跑得最快的5匹马?不能使用撞大运的算法

    解答:目前网上最典型的算法认为是10次

    (1) 首先将25匹马分成5组,并分别进行5场比赛之后得到的名次排列如下:
    A组: [A1 A2 A3 A4 A5]
    B组: [B1 B2 B3 B4 B5]
    C组: [C1 C2 C3 C4 C5]
    D组: [D1 D2 D3 D4 D5]
    E组: [E1 E2 E3 E4 E5]
    其中,每个小组最快的马为[A1、B1、C1、D1、E1]。
    (2) 将[A1、B1、C1、D1、E1]进行第6场,选出第1名的马,不妨设 A1>B1>C1>D1>E1.
    此时第1名的马为A1。
    (3) 将[A2、B1、C1、D1、E1]进行第7场,此时选择出来的必定是第2名的马,不妨假设为B1。因为这5匹马是除去A1之外每个小组当前最快的马。
    (3) 进行第8场,选择[A2、B2、C1、D1、E1]角逐出第3名的马。
    (4) 依次类推,第9,10场可以分别决出第4,5名的吗。

    因此,依照这种竞标赛排序思想,需要10场比赛是一定可以取出前5名的。

  • 相关阅读:
    《算法》第二章部分程序 part 3
    《算法》第二章部分程序 part 2
    《算法》第二章部分程序 part 1
    《算法》第一章部分程序 part 2
    《算法》第一章部分程序 part 1
    Java,Hello World,《算法》环境搭建中的问题,用 cmd 和 IntelliJ Idea 分别编译和运行 Java 程序
    《汇编语言 基于x86处理器》第十一章 MS-DOS 编程部分的代码 part 1
    《汇编语言 基于x86处理器》第十三章高级语言接口部分的代码 part 2
    《汇编语言 基于x86处理器》第十三章高级语言接口部分的代码 part 1
    《汇编语言》(王爽)补充笔记,第 14 ~ 17 章
  • 原文地址:https://www.cnblogs.com/deverz/p/9554231.html
Copyright © 2011-2022 走看看