您的位置:首页 > 其它

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

2017-11-02 21:51 211 查看

题目概述

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

解题报告

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

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

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

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

(黑历史完……)

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

枚举在哪里扔,要考虑碎掉和不碎掉两种状态的最坏情况,即 max(f[i−1][j−1],f[n−i+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
[m]) return f
[m];
f
[m]=MAXINT;
for (int i=2;i<=n;i++)
{
int now=max(Solve(i-1,m-1),Solve(n-i+1,m))+1;
f
[m]=min(f
[m],now);
}
return f
[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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: