Gym 100935H Bend Test and POJ 3783 Balls【经典的扔鸡蛋问题 + dp】

传送门
// 这道题就是最经典的扔鸡蛋问题, 也是一道经典dp问题. 问i个鸡蛋测j层楼最坏的情况下最少扔几次.

我们设dp[i][j] 表示有i个鸡蛋测j层楼满足条件的方案数, 首先枚举测的楼层, 然后考虑其中的每一层楼k, 如果在第k层楼碎了, 那么我们就必须要用i-1个鸡蛋去测k-1层楼, 如果没碎, 那么就是用i个鸡蛋去测j-k层楼, 然后取这这两种情况的max是因为要是最坏的情况, +1表示这次扔的, 然后在和自己取min即可, 所以我们的状态转移方程就是dp[i][j] = min(dp[i][j], max(dp[i-1][k-1], dp[i][j-k]) + 1) (1 <= k <= j) ; 那么就这样一直枚举到全部答案就行啦. 复杂度为O(n*m^2).

注意下初始状态, 1个鸡蛋时方案数就等于楼层数. 不管多少个鸡蛋0层楼是就是0, 一层楼时就是1. 然后枚举即可. (不会有0个鸡蛋的情况, 有的话也是0)

初始状态为: 一个鸡蛋, 和 0, 1层楼的情况即可.

AC Code

const int maxn = 1e3+5;
ll dp[55][maxn];
void init() {
    for (int i = 1 ; i <= 50 ; i ++) Fill(dp[i], inf);
    for (int i = 0 ; i <= 1000 ; i ++) dp[1][i] = i;
    for (int i = 1 ; i <= 50 ; i ++) dp[i][1] = 1, dp[i][0] = 0;
    for (int i = 2 ; i <= 50 ; i ++) {
        for (int j = 2 ; j <= 1000 ; j ++) {
            for (int k = 1 ; k < j ; k ++) {  //枚举该楼层是否会碎.
                dp[i][j] = min(dp[i][j], max(dp[i-1][k-1], dp[i][j-k])+1);
            }
        }
    }
}
void solve()
{
    int n, m ;
    cin >> n >> m ;
    cout << dp[n][m] << endl;
}

你可能感兴趣的:(dp思维)