2个鸡蛋100层楼/2个玻璃珠39层楼

题目描述:

你拿着两个鸡蛋站在100层的大楼上。鸡蛋或许结实到从楼定掉下也不会摔碎,或许很易碎。最少试验多少次可以找出鸡蛋被摔碎的最低楼层?

腾讯2017笔试题也有类似的题目,描述是针对2个玻璃珠和39层楼。

题目分析:

假定鸡蛋被摔碎的最低楼层我们称之为临界层。

有两个鸡蛋,第一次测试时,第一个鸡蛋不能放置的楼层太高,否则,如果第一个鸡蛋破碎了,那么第二个鸡蛋就必须在第一层试验的楼层以下,从一楼一层一层地往上试验直到找到临界层;但是也不能放置的太矮,如果第一个鸡蛋破碎了倒是可以缩小下次试验的楼层范围,但如果没破碎,我们便浪费了将这次试验机会的所能缩小的范围最大化。所以必须选择一个合适的楼层作为第一次测试的楼层。

假设总共耗费k次试验机会一定能试验出临界层。

情况一,我们考虑第一次试验,若鸡蛋破碎了,记住此时的楼层数为k';那么我们第二次从一楼开始往上一层一层地试验,最坏的情况是到k'-1层第二个鸡蛋都没碎,但是这时我们总共试验了k'次,还要考虑我们只有k次机会的前提,所以k'=k,也就是说,第一次测试时我们需要从第k层开始试验。

情况二,考虑另一种情况,假如第一次试验的鸡蛋没有破碎,那么我们失去了一次机会,此时需要从k+1层楼往上试验,那么重点来了,我们第二次选第几层开始试验呢?想一想,我们刚才浪费了一次机会,此时剩余k-1次机会,我们还是应该回归到情况一,得出的结论是下一次需要从k+(k-1)层开始试验(因为我们这次是从第k+1层开始算起),如果鸡蛋一直没碎,我们就需要重复上述过程知道最后一次机会,此时总共的测试楼层数为:k+(k-1)+(k-2)+(k-3)+……+2+1 = k*(k+1)/2。

回到题目,100层楼/2个鸡蛋或者39层楼/2个玻璃珠,k次试验找出临界层,试验的楼层数k*(k+1)/2大于等于总的楼层数,根据这个不等式便可以计算出k值。

对于100层楼,总共试验14次;对于39层楼,总共试验9次。


==================分隔线===================


转载自:http://www.cnblogs.com/jostree/p/4098409.html


使用动态规划算法,使用dp[i][j]表示对于i层楼并拥有j个鸡蛋时能够判断鸡蛋质量需要的最少次数。

假如我们在第k层扔下一个鸡蛋,则有两种情况,如果鸡蛋没有损坏则问题相当于我们对于i-k层楼拥有j个鸡蛋所需的最少的次数。

如果鸡蛋碎了,则问题相当于对于k层楼拥有j-1个鸡蛋的最小次数。从而可以得到动态规划公式:

dp[i][j] = Min( Max( dp[k][j-1], dp[i-k][j] ) ) ,  k ∈ [1. i)

数学方法推导:

如果我们有2个鸡蛋,k次投掷机会,那么第一次在k层投掷,如果坏掉,则从第一层往上一层一层的投。

否则剩下k-1次机会,所以要在k+(k-1)层投掷,如此往复,两个鸡蛋可以投掷的最高楼层为:

k+(k-1)+(k-2)+……+1 = k(k+1)/2

对于3个鸡蛋k次机会,根据上面的结论,两个鸡蛋k-1次可以试k(k-1)/2层楼。

所以第一次在k(k-1)/2+1层投,如果坏掉,则按2个鸡蛋共k(k-1)/2的方式投掷。

否则剩下k-1次机会和3个鸡蛋,则在此基础上增加(k-1)(k-2)/2+1层投掷,。

如此往复,三个鸡蛋可以投掷的最高层为:

((k(k-1)/2)+1) + (((k-1)(k-2)/2)+1) + ... ... + 1 = (k^3 + 5k)/6


import java.util.Scanner;

public class EggFloor {
	private static final int FLOORS = 1001;
	private static final int EGGS = 51;
	private static int dp[][];
	
	public static int resolve(int eggs, int floors) {
		dp = new int[FLOORS][EGGS];
		for(int i = 1; i <= floors; i++) {
			dp[i][1] = i-1;
		}
		for(int i = 1; i <= eggs; i++) {
			dp[1][i] = 0;
		}
		for(int i = 2; i <= floors; i++) {
			for(int j = 2; j <= eggs; j++) {
				int tmp = Integer.MAX_VALUE;
				for(int k = 1; k < i; k++) {
					tmp = Math.min(tmp, Math.max(dp[k][j-1], dp[i-k][j]));
				}
				dp[i][j] = tmp + 1;
			}
		}
		return dp[floors][eggs];
	}
	
	public static void main(String[] args) {
		Scanner scanner = new Scanner(System.in);
		int count = scanner.nextInt();
		while(count-- != 0) {
			int cnt, eggs, floors;
			cnt = scanner.nextInt();
			eggs = scanner.nextInt();
			floors = scanner.nextInt();
			System.out.println(cnt + " " + resolve(eggs, floors));
		}
		scanner.close();
	}

}






你可能感兴趣的:(Algorithm)