LeetCode 887. Super Egg Drop

You are given K eggs, and you have access to a building with N floors from 1 to N

Each egg is identical in function, and if an egg breaks, you cannot drop it again.

You know that there exists a floor F with 0 <= F <= N such that any egg dropped at a floor higher than F will break, and any egg dropped at or below floor F will not break.

Each move, you may take an egg (if you have an unbroken one) and drop it from any floor X (with 1 <= X <= N). 

Your goal is to know with certainty what the value of F is.

What is the minimum number of moves that you need to know with certainty what F is, regardless of the initial value of F?

Example 1:

Input: K = 1, N = 2
Output: 2
Explanation: 
Drop the egg from floor 1.  If it breaks, we know with certainty that F = 0.
Otherwise, drop the egg from floor 2.  If it breaks, we know with certainty that F = 1.
If it didn't break, then we know with certainty F = 2.
Hence, we needed 2 moves in the worst case to know what F is with certainty.

Example 2:

Input: K = 2, N = 6
Output: 3

Example 3:

Input: K = 3, N = 14
Output: 4

Note:

  1. 1 <= K <= 100
  2. 1 <= N <= 10000

概述

    求 [0~N] 升序列的极小最大查找次数。限定了鸡蛋数,如果查找后发现目标在二分点右侧(大于等于楼层),鸡蛋-1.

    以下用一个从左到右的数轴代替拔地而起的楼层来说明,在n层扔鸡蛋相当于把序列分割为[0,n-1],[n~N]。

思路

    我一开始想找出解析表达式,WA多次后反复推导模型,发现只有递推关系式...

    这道题看似一道与二分相关的复杂贪心题,实际很容易找出dp解法。

    首先需要想到的思路方向是,解法应当寻找给定K,F对应可搜索的楼层上界,而不是从K,N计算F,从K,N计算无规律可循。

    然后想到K和F都会影响F上界。F增加,在鸡蛋没摔破时相当于K增加。

    最后跟着DP的思路,发现在K个鸡蛋,限定F行动数的条件下扔鸡蛋后,要求在K,F-1条件下处理分割后的左数组;而右边的条件是K-1,F-1.

    进一步易证,一组K,F对应的楼层上界,等于扔一个鸡蛋后左右两边余下K,F对应的楼层上界之和

  •     每一次行动中,除了扔鸡蛋外别无选择,而不论怎样,扔鸡蛋后被分割出的左右两段,它们的余下K,F是一定的。

    这样我们就得到了一个递推关系式:dp[i][j] = dp[i-1][j-1] + dp[i][j-1],dp[i][0]=1,

    其中i表示鸡蛋数K,j表示行动数F,以楼层上界为状态dp[i][j].

    观察递推式中j非常乖巧,可对j迭代,一维dp实现。当dp[K]第一次大于等于N+1时输出j.(0~N共N+1个数)

    由于K比N小得多,不用担心dp数组不必要地过大。

代码

class Solution {
public:
    int superEggDrop(int K, int N) {
        int dp[K+1];
        for(int i=0;i<=K;i++)
            dp[i]=1;
        int r=0;
        while(dp[K]<N+1){
            for(int i=K;i>0;i--)
                dp[i]+=dp[i-1];
            r++;
        }
        return r;
    }
};

http://www.cnblogs.com/hizcard/  转载请注明出处 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值