poj 3783 Balls 动态规划 100层楼投鸡蛋问题

作者:jostree 转载请注明出处 http://www.cnblogs.com/jostree/p/4098409.html

题目链接:poj 3783 Balls 动态规划 100层楼投鸡蛋问题

使用动态规划算法,使用$dp[i][j]$表示对于i层楼并拥有$j$个鸡蛋时能够判断鸡蛋质量需要的最少次数。
假如我们在第$k$层扔下一个鸡蛋,则有两种情况,如果鸡蛋没有损坏则问题相当于我们对于$i-k$层楼拥有$j$个鸡蛋所需的最少的次数。
如果鸡蛋损坏了,则问题相当于对于k层楼拥有$j-1$个鸡蛋的最小次数。从而可以得到动态规划公式:

\begin{equation}
dp[i][j] = Min(Max(dp[k][j-1],dp[i-k][j])),k\in[1,i)
\end{equation}

数学方法推倒:

如果我们有$2$个鸡蛋,$k$次投掷机会,那么第一次在$k$层投掷,如果坏掉,则从第一层往上投。
否则剩下$k-1$次机会,所以要在$k+(k-1)$层投掷,如此往复,两个腕带可以投掷的最高楼层为:

\begin{equation}
\sum_{i=1}^k i = \frac{k(k+1)}{2}
\end{equation}

对于三个鸡蛋k次机会,根据上面的结论,两个鸡蛋$k-1$次可以测试$k(k-1)/2$层楼,所以第一次在$k(k-1)/2+1$层投,如果坏掉,则从第一层往上投。
否则剩下k-1次机会和两个鸡蛋,则在此基础上增加$(k-1)(k-2)/2+1$层投掷,如此往复。三个鸡蛋可以投掷的最高层为:

\begin{equation}
\sum_{i=1}^k \frac{i(i-1)}{2}+1 = \frac{k^3+5k}{6}
\end{equation}

代码如下:

 1 #include <cstdio>

 2 #include <cstdlib>

 3 #include <iostream>

 4 #include <cstring>

 5 #include  <limits.h>

 6 #define     MAX_F 1001

 7 #define     MAX_E 100

 8 using namespace std;

 9 int dp[MAX_F][MAX_E];

10 int solve(int floor, int egg)

11 {

12     memset(dp, 0, sizeof(dp));

13     for( int i = 1 ; i <= floor ; i++ )

14     {

15         dp[i][1] = i-1;

16     }

17     for( int i = 1 ; i <= egg  ; i++ )

18     {

19         dp[1][i] = 0;

20     }

21     for( int i = 2 ; i <= floor ; i++ )

22     {

23         for( int j = 2 ; j <= egg ; j++ )

24         {

25             int tmp = INT_MAX;

26             for( int k = 1 ; k < i ; k++ )

27             {

28                 tmp = min(tmp, max(dp[k][j-1] , dp[i-k][j]));

29             }

30             dp[i][j] = tmp+1;

31         }

32     }

33     return dp[floor][egg];

34 }

35 int main(int argc, char *argv[])

36 {

37     int t;

38     scanf("%d", &t);

39     while( t-- )

40     {

41         int n, egg, floor;

42         scanf("%d%d%d", &n, &egg, &floor);

43         printf("%d %d\n",n, solve(floor, egg));

44     }

45 }
View Code

 

你可能感兴趣的:(动态规划)