【DP】RQNOJ107[Ural的鹰蛋实验]题解

来源:互联网 发布:mac客人用户退出不了 编辑:程序博客网 时间:2024/05/16 14:38

题目概述

经典的鹰蛋问题,就因为懒所以不写了。

解题报告

不知道大家第一想法是不是二维DP,反正我不是……

2015年,当我还是普及组大菜鸡(现在是提高组大菜鸡)时,我看到了这道题。

然后根本不会,直到教练下发题解……

题解上是……没错……区间DP f[L][R][egg] ……

(黑历史完……)


显然所有区间都是等价的,唯一重要的是区间长度,所以可以定义 f[i][j] 表示区间长度为 i ,目前还有 j 个鹰蛋的最优解。

枚举在哪里扔,要考虑碎掉和不碎掉两种状态的最坏情况,即 max(f[i1][j1],f[ni+1][j])+1 ,然后从所有最坏情况中选出最小值,得到 f[i][j]

然而这样效率是 O(n2m) ,显然无法承受。此时会想到明显错误但是最优的答案 p=log2n ,当鸡蛋数超过 p 时,显然答案就是 p ,那么复杂度缩减为 O(n2log2n)

然后?其实还可以优化,但是我不会:P,可以看dalao的论文。

示例程序

记忆化大法好。

#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int maxn=1000,maxm=10,MAXINT=((1<<30)-1)*2+1;int n,m,f[maxn+5][maxm+5];inline int Log(int n) {for (int i=0;;i++) if ((1<<i)>=n) return i;}int Solve(int n,int m){    int p=Log(n);if (p<=m) return p;    if (n==1) return 0;if (m==1) return n-1;if (~f[n][m]) return f[n][m];    f[n][m]=MAXINT;    for (int i=2;i<=n;i++)    {        int now=max(Solve(i-1,m-1),Solve(n-i+1,m))+1;        f[n][m]=min(f[n][m],now);    }    return f[n][m];}int main(){    freopen("program.in","r",stdin);    freopen("program.out","w",stdout);    memset(f,255,sizeof(f));    while (~scanf("%d%d",&m,&n)) printf("%d\n",Solve(n+1,m));    return 0;}
原创粉丝点击