代码改变世界

鬼魂算法

2012-09-23 12:31  ggzwtj  阅读(4032)  评论(15编辑  收藏  举报

这个方法的名字是从一个大学同学那里得来的。算法本身非常简单,但是这个名字太酷了,所以决定写下来。

题目一:

一个管子里有N个球,它们都在以1M/S的速度(向左或向右)移动,在两个球发生碰撞时,各自掉头并且速度不变,问:多长时间之后N个球全部落地?

相信很多泡过论坛的人这个题目不只见过一次,而解决方法也很简单。为了方便下面进一步的说明,这里赘述一下:

如果换个描述的方法:两个球在相遇的时候,他们并没有发生碰撞而是互相穿越而过(就像两个鬼魂相遇时一样),但是他们的编号互换了。显然,这种描述和题目中的描述是等价的。在这种描述下问题就很好解决了,球与球之间并没有发生碰撞,它沿着它开始的方向移动到对应的尽头便落下,算出所有球中的最大值便是所有球落下的时间。

题目二:

描述同题目一,问:时间T时,求I的位置?

这个问题把题目一往前稍微提了一点点,因为这时候要考虑碰撞了(不然编号什么的都乱了)。这里想一下:

a、其他球的碰撞重要吗?

b、相同方向的球可能相遇吗?

为了更直观的看问题,这里画一个图:

其中白色的球向右,黑色的球向左,标号为i的白球是我们要计算的,现在再来看上面的两个问题。其他球发生碰撞的时候,对球I来说是没有关系的,因为如擦掉球的颜色,在任何碰撞之后整体的情况对I球来说和擦身而过是相同的效果。相同方向的球因为速度相同,永远也不可能相撞。但是,这里要考察的是I球的位置,所有I球的碰撞是需要考虑的。那么问题的解决方法便出来了:

a、忽略其他球之间的碰撞,只考虑I球和其他球的碰撞。

b、每个位置的球只可能和I球碰撞一次,因为碰撞之后方向变为同向。

到这里就差不多了,那么来看下碰撞的规律吧:

根据上面的a、b两条,那么总是白球和黑球相撞,而每次相撞的时间点就是这两个球之间的距离/2。显然随着碰撞时间递增,所以可以依次计算每次碰撞的时间直到满足时间,当然也可以用二分。

------------------------------------------

欢迎拍砖。