F - F HDU - 3281 Balls(动态规划)

Balls(背包问题变形)

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

思路

  • 题意:给我n个小玻璃球,和一个h层高的建筑,玻璃球从这个建筑物的某一层落下可能碎,也可能不碎,让我找某一层k,在k层及以上小球被扔下来都是碎的,而在k层一下被扔下来不碎,为了找到这个第k层在“最糟糕的情况下”我们需仍多少次小球,这里的“最糟糕情况指的是在某次在某一层扔小球之后,如果小球碎裂,我们需要最少在抛小球x次,如果不碎最少需要抛小球y,我们总是取max(x,y)次”
  • 思路:没有想到竟然是dp问题,,,我们考虑小球从第层被扔下有碎和不碎两个状态(设没抛小球之前总共有j个小球)
  1. 如果小球碎了,那么它的状态转移就是dp[k-1][j-1],k-1指的是,既然第k层碎了我只需要查找第1~k-1层是否碎就行了
  2. 如果小球不碎,我们我们可以确定1~k层均不回碎,那么我们只需要找k+1~h层在那一层恰好碎,这个时候的问题就相当于转化为 在一个有 h-k层高的建筑物上,我们手里有j个小球问我需要多少次最少抛找到恰好碎的那一层,所以这个时候的状态转移为 dp[n-k][j]

代码

#include<iostream>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<map>
using namespace std;
void fre() { freopen("A.txt","r",stdin), freopen("Ans.txt","w",stdout); }
#define ll long long 
const int mxn = 100005;
int dp[1005][55];       //dp[i][j] == k 表示当有i层,j个球的情况下最少仍的次数为k次
int main()
{
    /* fre(); */
    int t;
    scanf("%d", &t);
    while(t --)
    {
        int num, n, h;
        scanf("%d %d %d", &num, &n, &h);

        memset(dp, 0x3f, sizeof(dp));
        for(int i = 0; i <= n; i ++)    //如果是第0层,那么最少仍的次数均为0——————初始化状态
            dp[0][i] = 0;

        for(int i = 1; i <= h; i ++)            //枚举建筑高度
            for(int j = 1; j <= n; j ++)        //枚举小球的数量
                for(int p = 1; p <= i; p ++)    //枚举从第p层开始扔小球
                {
                    //当小球从第p层扔下,有两个状态 要么碎,要么不碎
                    //如果碎了的话,很明显接下来我们要考虑的是,在[1, p-1]层中的那一层会出现恰好碎的情况,这个时候的状态转为 dp[p-1][j-1]
                    //如果不碎的话,我们接下来需要考虑 [p+1~i]层中那一层是恰好碎的那一层,由于求[p+1~i]之间那一层碎等价于求[1, i-p] 层那一层会出现恰好碎的情况,那么这个时候的状态转移为dp[i-p][j]
                    //因为是让求“最糟糕的情况”,所以我们要在两种情况之间选择较大的那个
                    int tmp = max(dp[p-1][j-1], dp[i-p][j]) + 1;  //这里的+1 是进行了一次抛球操作
                    //这里求最小值,是因为题目让让我求最小抛
                    dp[i][j] = min(dp[i][j], tmp);
                }
        printf("%d %d\n", num, dp[h][n]);
    }

    return 0;
}

猜你喜欢

转载自www.cnblogs.com/lql-nyist/p/12742740.html
F