ZCMU 1894: Power Eggs

http://acm.zcmu.edu.cn/JudgeOnline/problem.php?id=1894

题意:

有M个鹰蛋,N层楼,鹰蛋的硬度是E,也就是说在1~E层楼扔下去不会碎,E+1层楼扔下去会碎。

给定M,N,问最坏情况下至少几次能得到E的具体的值。(E可能为0)

①n<=100。

②n<=1000。

③n<=100000。

④n<=1000000。

⑤n<=1000000000。

推荐学习资料: 朱晨光IOI2004集训队论文 从《鹰蛋》一题浅析对动态规划算法的优化

算法一: O(n^3)

dp[i][j] 表示用i个蛋在j层楼上确定E,最坏情况下的最少次数

枚举在第w层扔下1个蛋,要么碎,要么不碎

碎:用剩下的i-1个蛋在下面的w-1层里确定E

不碎:剩下的i个蛋在 w+1~n 层里确定E,这相当于在 下面的n-w 层确定E

所以dp[i][j]=min{ max(dp[i-1][w-1],dp[i][j-w]) } +1

事件复杂度为 O(n^2 * m),m认为与n同阶

算法二:O(n^2 * logn)

根据判定树的理论,长为n的有序线性表,最坏查找需要次数为logn [上取整]

所以当鹰蛋的个数超过 log(n+1) [上取整] 时,直接输出log(n+1) [上取整]

算法三:O(n*logn*logn)

比较显然的结论:dp[i][j]>=dp[i][j-1]

(严谨的证明去看论文)

dp[i][j]=min{ max(dp[i-1][w-1],dp[i][j-w]) } +1

dp[i-1][w-1] 随w的增大单调不减

dp[i][j-w] 随w的增大单调不增

对于每一个w,对应的这两条线谁在上面就取谁

所以最终更新 dp[i][j]的w是这两条线的交点

可以二分找这个w

算法四:O(n*logn)

dp[i][j]=min{ max(dp[i-1][w-1],dp[i][j-w]) } +1

对于任意的w,满足 dp[i][j]<= max(dp[i-1][w-1],dp[i][j-w])  +1

令w=1,那么dp[i][j]<= max(dp[i-1][0],dp[i][j-1])  +1

所以dp[i][j]<=dp[i][j-1]+1

所以 dp[i][j-1]<=dp[i][j]<=dp[i][j-1]+1

所以若存在一个w,能够使得dp[i][j]=dp[i][j-1],则dp[i][j]=dp[i][j-1]

若对于所有的w,都不能使得dp[i][j]=dp[i][j-1],则dp[i][j]=dp[i][j-1]+1

令p满足 dp[i][p]=dp[i][j-1]-1,dp[i][p+1]=dp[i][j-1]

那么dp[i][p]=dp[i][j-1]-1

dp[i][p+1]=dp[i][p+2]=……=dp[i][j-1]

计算dp[i][j]时,令j-w=p,则w=j-p

则 dp[i][j]=min{ max(dp[i-1][j-p-1],dp[i][p])  }

可以证明

当 dp[i-1][j-p-1]<=dp[i][p] 时,dp[i][j]=dp[i-1][j]

当 dp[i-1][j-p-1]>dp[i][p] 时,dp[i][j]=dp[i-1][j]+1

具体证明去看论文

算法五:

dp[i][j] 表示 用i个蛋,扔j次最坏情况下最大能确定的楼层数

扔一次碎了,那么剩下j-1次,剩下i-1个蛋

我们也希望用剩下的次数和剩下的蛋在下面能确定的楼层数最大,所以是dp[i-1][j-1]

扔一次没碎,那么剩下j-1次,剩下i个蛋

我们也希望用剩下的次数和剩下的蛋在上面能确定的楼层数最大,所以是dp[i][j-1]

加上扔蛋的这一次

所以 dp[i][j]=dp[i-1][j-1]+dp[i][j-1]+1

如果只有一个蛋,只能1层1层的试,dp[1][i]=i

如果只有一层,dp[i][1]=1

初始化和转移都跟 组合数C 很像

C爆炸式增长,所以这个也是爆炸式增长

论文里有证明

也就是说当n很大的时候,i和j很小

当n=2e9时,i和j只取到32就A了

#include<cstdio>

using namespace std;

typedef long long LL;

LL dp[33][33];

void DP()
{
    for(int i=1;i<=32;++i) dp[i][1]=1,dp[1][i]=i;
    for(int i=2;i<=32;++i)
        for(int j=2;j<=32;++j)
            dp[i][j]=dp[i][j-1]+dp[i-1][j-1]+1;
}

int main()
{
    DP();
    int T;
    scanf("%d",&T);
    int n,m,ans;
    while(T--)
    {
        scanf("%d%d",&n,&m);
        ans=-1;
        for(int i=1;i<=32;++i)
            if(dp[m][i]>=n) { ans=i; break; }
        if(ans==-1) puts("Impossible");
        else printf("%d\n",ans);
    }
}

原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/8453790.html

时间: 2024-08-06 01:01:38

ZCMU 1894: Power Eggs的相关文章

[LeetCode] Power of Three

Given an integer, write a function to determine if it is a power of three. Follow up:Could you do it without using any loop / recursion? 判断一个数是否是3的幂,则这个数a的所有的约数都是3的幂,如果一个数b小于这个数a且是3的幂,则这个数b一定是a的约数.所以找出3的最大的幂,然后用这个数对n取余即可. class Solution { public: boo

poj 3134 Power Calculus(迭代加深dfs+强剪枝)

Description Starting with x and repeatedly multiplying by x, we can compute x31 with thirty multiplications: x2 = x × x, x3 = x2 × x, x4 = x3 × x, …, x31 = x30 × x. The operation of squaring can be appreciably shorten the sequence of multiplications.

POJ 3233 - Matrix Power Series ( 矩阵快速幂 + 二分)

POJ 3233 - Matrix Power Series ( 矩阵快速幂 + 二分) #include <cstdio> #include <cstring> #include <algorithm> using namespace std; typedef long long LL; #define MAX_SIZE 30 #define CLR( a, b ) memset( a, b, sizeof(a) ) int MOD = 0; int n, k; st

Power BI教程_Power BI数据分析快速上手及案例实战

Power BI数据分析快速上手及案例实战 课程学习地址:http://www.xuetuwuyou.com/course/194 课程出自学途无忧网:http://www.xuetuwuyou.com 课程简介 本课程在<Power BI 数据分析快速上手>基础上结合大量的实例,深入讲解PowerBI中看似难懂的各种概念.操作, 并结合行业中的典型案例贯穿了从初级的数据透视表工具.数据透视表选项.数据透视表的刷新.数据透视表中的排序,到中级的动 态数据透视表的创建.数据透视表函数 GETPI

leetcode 231. Power of Two

Given an integer, write a function to determine if it is a power of two. class Solution { public: bool isPowerOfTwo(int n) { int num = 0; while (n > 0) { if (n &1) num++; n/=2; } if (num == 1) return true; return false; } };

[LeetCode] Power of Two

Given an integer, write a function to determine if it is a power of two. 判断一个整数是否是2的幂.如果一个数是2的幂,则这个数的二进制表示中,最高位是1,其他位都是0.这个数-1的二进制位全是1.所以我们可以利用这个规律对两个数取与进行判断. class Solution { public: bool isPowerOfTwo(int n) { if (n <= 0) return false; return !(n &

POWER(x,y)

POWER(x,y) 用于返回 x 的 y 次方的结果 mysql> SELECT POWER(2,4), POWER(2,-4); +------------+-------------+ | POWER(2,4) | POWER(2,-4) | +------------+-------------+ | 16 | 0.0625 | +------------+-------------+

Oracle学习-Power Designer、visio 2003、Oracle sql developer、OEM、expdp

Oracle的体系太庞大了.对于刚開始学习的人来说,难免有些无从下手的感觉. 经过一学期的学习对Oracle学习有了一些深入的了解,由于之前学习过Oracle的一些主要的知识.所以学习起来上手比較快一点. 这次Oracle项目让我又一次对Oracle的基本知识进行了运用,而且对软件project也有了新的认识.从需求分析.概念结构设计.逻辑结构设计.物理结构设计.数据库的建立和測试.数据库执行和维护. 尽管说数据库设计的周期比較长将近用了三周左右,可是每一步做的还是非常认真的对待.我选择的是舰队

Android Framework层Power键关机流程(二,关机流程)

二,关机流程 从前一篇博文我们知道,当用户长按Power键时会弹出(关机.重新启动,飞行模式等选项)对话框,我们点击关机,则会弹出关机确认对话框.那么从选项对话框到关机确认对话框又是一个什么流程呢.以下我们在简单分析一下: showGlobalActionsDialog()-->showDialog()-->handleShow()-->createDialog()-->onPress()-->shutdown() PhoneWindowManager.java void s