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名的。

  • 相关阅读:
    POJ 3126 Prime Path
    POJ 2429 GCD & LCM Inverse
    POJ 2395 Out of Hay
    【Codeforces 105D】 Bag of mice
    【POJ 3071】 Football
    【POJ 2096】 Collecting Bugs
    【CQOI 2009】 余数之和
    【Codeforces 258E】 Devu and Flowers
    【SDOI 2010】 古代猪文
    【BZOJ 2982】 combination
  • 原文地址:https://www.cnblogs.com/deverz/p/9554231.html
Copyright © 2011-2022 走看看