- 题目
你在一幢100层的办公楼里上班,现在给你两台xbox(已经特意捆绑包扎好),要求你用尽可能少的试摔次数来判断xbox摔不坏的最高楼层层数。比方说,从30层丢下来没问题,但从31层丢下来就不保了。在摸索过程中,允许把两台xbox都砸烂。在最坏情况下,使得试摔次数尽可能小。
- 分析
- 问题答案必须是在最坏情况下,时间复杂度最小。
- 最容易想到的就是二分法,三分法,多分法,但它们并不符合要求。比如:在50层丢一个,被砸烂。然后在25层丢另外一个,同样被砸烂。此时根本无从找到问题答案。
- 第二个想到的方法就是分段。(1)用第一个xbox寻找损坏区间;(2)用第二个xbox遍历该区间寻找损坏层。假定最优区间长度是x,则第一步最多要摔100/x(大于等于此值的最小整数)次,第二步最多摔x-1次,问题转换为求100/x+(x-1)的最小值。具体描述:以10层楼为一个区间,先摔第一个,以确定摔坏的区间,然后再用另一个在这个区间内从最低的楼层摔,从而找到所要求层数,这种方法最多要摔19次。
- 在“分段”方法中,段区间都是相等的。如果段区间不等,是不是可以找到最优的方法呢?假设最终答案至少要摔n次,那第一次顶多从n层楼摔。如果坏了,第二 个从1至n-1层最多摔n-1次就可以判断了;如果没坏,那么搜索范围改为[n+1,100],相当于搜索空间减少了n层。如果第一次没坏,第二次顶多再 减少n-1的搜索空间。依次类推,当第n次时顶多再减少1的搜索空间。n次之后,顶多排除n+(n-1)+(n-2)+...+1 = n*(n+1)/2个楼层。只要n*(n+1)/2 >= 100就可以了,满足这个条件的最小n为14。具体描述:从14楼丢一个,如果碎了,从1楼开始到13楼为止丢另一个,不碎,在14+13楼丢;...
- 证明
sigma<k=1>( cost[k] )
= (1+a[1]-1) + (2+a[2]-1) + (3+a[3]-1) ... + (n+a[n]-1)
= (1+2+3+ ... +n) + (a[1]+a[2]+a[3]+ ... +a[n]) - n
= n*(n+1)/2 + 100 - n
这个式子是个常量仅与n有关,与{a[1],...,a[n]}的具体数值无关。同时,不难看出 max<k=1>( cost[k] ) >= sigma<k=1>( cost[k] ) / n (最大值总是大于平均值),而且仅当 cost[1] =cost[2] = ... cost[n] 的时候,max...可以取到这个最小值。因此,对于任意给定的n,满足 cost[1]= cost[2] = ... cost[n]的解就是最优解。也就是说k+a[k]-1=1+a[1]-1,从而a[k]=a[1]-k+1 。那么a[2]=a[1]-1,a[3]=a[1]-2=a[2]-1...
参考:(1) 摔xbox的题目</k=1></k=1></k=1></k=1>