poj3783 Balls

Balls
Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 1110   Accepted: 721

Description

The classic Two Glass Balls brain-teaser is often posed as: 

"Given two identical glass spheres, you would like to determine the lowest floor in a 100-story building from which they will break when dropped. Assume the spheres are undamaged when dropped below this point. What is the strategy that will minimize the worst-case scenario for number of drops?"


Suppose that we had only one ball. We'd have to drop from each floor from 1 to 100 in sequence, requiring 100 drops in the worst case. 

Now consider the case where we have two balls. Suppose we drop the first ball from floor n. If it breaks we're in the case where we have one ball remaining and we need to drop from floors 1 to n-1 in sequence, yielding n drops in the worst case (the first ball is dropped once, the second at most n-1 times). However, if it does not break when dropped from floor n, we have reduced the problem to dropping from floors n+1 to 100. In either case we must keep in mind that we've already used one drop. So the minimum number of drops, in the worst case, is the minimum over all n. 

You will write a program to determine the minimum number of drops required, in the worst case, given B balls and an M-story building.

Input

The first line of input contains a single integer P, (1 ≤ P ≤ 1000), which is the number of data sets that follow. Each data set consists of a single line containing three(3) decimal integer values: the problem number, followed by a space, followed by the number of balls B, (1 ≤ B ≤ 50), followed by a space and the number of floors in the building M, (1 ≤ M ≤ 1000).

Output

For each data set, generate one line of output with the following values: The data set number as a decimal integer, a space, and the minimum number of drops needed for the corresponding values of B and M.

Sample Input

4 
1 2 10 
2 2 100 
3 2 300 
4 25 900

Sample Output

1 4
2 14
3 24
4 10

Source

题目大意:鹰蛋问题.n个蛋,m层楼. 存在一层楼E,使得E以及E以下的楼层鹰蛋都不会摔碎,问最坏情况下最少多少次能够知道E.
分析:这是一道神奇的题目.不仅仅是题目类型非常特别,优化也很多.具体的优化可以去看论文:传送门,这里只想说说这类问题如何下手.
   题目的目的是最小化最大值,似乎可以二分?可是什么都不知道要怎么判断可行性啊......正确的解法是dp.状态很明显:
   f[i][j]表示i个蛋,确定j层楼的E的答案. 如果当前在第k层扔蛋,两种可能:
   1.蛋碎了,那么还剩下i-1个蛋,第j层不是E层,还有j-1层需要确定,可以从f[i-1][j-1]转移而来. 
   2.蛋没碎,还剩下i个蛋,第k层以下都不可能是E层了,还剩下j-k层需要确定.那么从f[i][j - k]转移而来. 注意,这里的从上往下数j-k层和从下往上数j-k层本质上是没有区别的,所以可以把这j-k层看作一个新的高j-k层的楼.
   接着就是重中之重了,如何转移? 事情总是朝着最坏的方向发展的. 第k层会不会摔碎实际上是不能确定的!要从最坏的状态转移而来!那么状态转移方程就是:f[i][j] = min{max{f[i-1][j-1],f[i][j - k]} + 1,f[i][j]}. 
   脑洞不大的话理解起来确实有点困难,比较好的方法是倒着看.从第k层状态的不确定性来从最坏的情况转移而来.
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

const int inf = 0x7ffffff;
int T;
int cas,n,m,f[3010][3010];

void solve()
{
    memset(f,127/3,sizeof(f));
    for (int i = 1; i <= n; i++)
        f[i][0] = 0;
    for (int i = 1; i <= m; i++)
        f[1][i] = i;
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= m; j++)
            for (int k = 1; k <= j; k++)
                f[i][j] = min(f[i][j],max(f[i - 1][k - 1],f[i][j - k]) + 1);
}

int main()
{
    scanf("%d",&T);
    while (T--)
    {
        scanf("%d%d%d",&cas,&n,&m);
        solve();
        printf("%d %d\n",cas,f[n][m]);
    }

    return 0;
}

 

posted @ 2018-03-01 21:11  zbtrs  阅读(267)  评论(0编辑  收藏  举报