问题描述可以见:http://datagenetics.com/blog/july22012/index.html
If an egg breaks when dropped from floor n, then it would also have broken from any floor above that. If an egg survives a fall, then it will survive any fall shorter than that. The question is: What strategy should you adopt to minimize the number egg drops it takes to find the solution?. (And what is the worst case for the number of drops it will take?) |
在鸡蛋无穷多的时候,计算方法同二分搜索;当只有一个鸡蛋的时候,那么为了找到确定的答案,只能从小到大依次递增,直至摔碎。
对于只有两个鸡蛋,我们可以先对第一只鸡蛋进行二分搜索,然后在第一只鸡蛋破了之后在进行从小到大的线性搜索(假设测试摔碎的层是n , 之前没碎的最大层是m, 那么第二只鸡蛋需要搜索的范围是m+1~n-1)。然而在最坏的情况下,上述两个方法不能够给出一个较为合适的解。再看一种情况,假设楼梯数是100层,让第一个鸡蛋以10层 往上递增,这样每次第二只蛋的最坏情况都是搜索9 次,这种情况下最坏的次数是10+9( 1: 10~100, 2: 91~99) 19次。
最好的情况是,两次鸡蛋尝试的总次数最小。假设破碎的楼层是N.我们假设最好的情况下,第一次加上第二次总共次数是k次。 第一颗鸡蛋在尝试第一次的时候,尝试k层,如果破裂,那么第二只鸡蛋需要尝试1~k-1层;如果没有破裂,那么第一只鸡蛋再尝试走k-1层,(而不是k层,因为第一只鸡蛋在做第二次尝试的时候已经又走了一步了),这样,一旦鸡蛋破了,那么第二只鸡蛋需要尝试k-2次,也就是从k+1层到2k-1。依次类推,就有了公式: n+(n-1)+...+1 >= N, 于是有n(n+1)/2.
写了个程序判断了下比最佳步伐小一步的情况下的结果,发现还是取比 n大的整数才是最好的结果。
代码:
package course;
public class TwoEggs {
public static void main(String args[]){
System.out.println(new TwoEggs().twoEggs(100));
System.out.println(new TwoEggs().twoEggs(200));
}
public int twoEggs(int n){
//1st egg jump, 2nd egg check through
//cal the worst scenarios, should use recursion
int count =1;
while( count*(count+1)/2 < n){
count++;
}
//尝试边界值两边的两种情况
//System.out.println(count);
int tmp1 = count;
int sum1 = 0;
int lastSum1=0;
int step1=0;
while(tmp1>0){
if(sum1+tmp1<=n){
//System.out.println("tmp1:"+ tmp1);
lastSum1=sum1;
sum1+=tmp1;
tmp1--;
step1++;
}else{
System.out.println("previous steps:"+step1);
if(n - sum1 > sum1-lastSum1-1)
step1 = n - sum1;
else step1+=sum1-lastSum1-1;//中间那几步都要试
System.out.println("rest try:"+ (sum1-lastSum1-1));
break;
}
}
System.out.println("total step:"+ step1);
//count -1
int tmp2 = count-1;
int sum2 = 0;
int lastSum2=0;
int step2=0;
while(tmp2>0){
if(sum2+tmp2<=n){
//System.out.println("tmp2:"+ tmp2);
lastSum2=sum2;
sum2+=tmp2;
tmp2--;
step2++;
}
}
if(n - sum2 > sum2-lastSum2-1)
step2 += n - sum2;
else step2 += sum2-lastSum2-1;
int resx = (n - sum2)>(sum2-lastSum2-1)?n - sum2:sum2-lastSum2-1;
System.out.println("rest step2:"+resx);
System.out.println("total step 2:"+ step2);
return step1;
}
}
想写一个直接给出最佳策略的算法,感觉不太好下手。。