鹰蛋问题

题目:

        一幢 100 层的大楼,给你两个鸡蛋。如果在第 n 层扔下鸡蛋,鸡蛋不碎,那么从第 n-1 层扔鸡蛋,都不碎。这两只鸡蛋一模一样,不碎的话可以扔无数次。最高从哪层楼扔下时鸡蛋不会碎?

1. 如果有无数个蛋

        用二分法就能在O(logn)的次数内求解问题

2.如果只有2个蛋

第一种:把楼层等分试探求解

        把楼层分为x等分,用第一鹰蛋从下往上依次试探一个范围,如果第一个鹰蛋破了,则用另一鹰蛋穷举。

假设把总楼层分成了X等份,每个等分内部有N/X个楼层。在最坏情况下,第一个蛋需要试探X次,第二蛋则要试探N/X - 1次(即在每个等份内做穷举),所以最坏情况需要的总次数为X + (N/X) -1。

要获取最坏情况的最小值,需要对总次数X + (N/X) -1求导数,并取0值,求解,可以得到X = sqrt(N)

第二种:动态规划

假设有m楼层,n个鹰蛋,则在第i层试探时会出现两种状态,一种状态是鹰蛋摔破了,则我们下一步只有n-1个鹰蛋,同时总楼层数也缩减为i-1,另一种状态是鹰蛋没有摔破,那么鹰蛋总数不变,还是n个,楼层数则缩减为m-i层。

递归在以下3个状态结束:

    1)如果鹰蛋只剩1个,那么只能对所有的楼层进行穷举;

    2)如果楼层是0,则需要试探0次;

    3)如果楼层是1,则需要只需要试探1次。

动态规划的状态转移方程:F(m,n)=  MAX{ F(i-1, n-1) + 1, F(m-i, n)+1};(0 < i < m)

通过array[M][N]来保存子问题的结果


public class yingdan {
	static int nfloor = 100;
	static int negg = 2;
	static int[][] arr = new int[nfloor][negg];

	public static void main(String[] args) {

		int a = test_egg(nfloor, negg);
		System.out.println(a);
	}

	static int test_egg(int nfloors, int neggs) {
		if (neggs <= 1)
			return nfloors;

		if (nfloors == 0)
			return 0;

		if (nfloors == 1)
			return 1;

		int min = nfloor;

		if (arr[nfloors - 1][neggs - 1] != 0)
			return arr[nfloors - 1][neggs - 1];

		for (int i = 1; i < nfloors; i++) {
			int a = test_egg(i - 1, neggs - 1) + 1;
			int b = test_egg(nfloors - i, neggs) + 1;
			int v = Math.max(a, b);

			if (min > v)
				min = v;
		}

		arr[nfloors - 1][neggs - 1] = min;

		return min;

	}

}

猜你喜欢

转载自blog.csdn.net/Broken_Wave/article/details/82020146