Ural 1223 & POJ 3783 鹰蛋问题
来源:互联网 发布:pc蛋蛋牛人10×0算法 编辑:程序博客网 时间:2024/05/10 16:15
昨晚队内练习赛做了Greater New York Regional 2009套题...水一套..不过还有有道很经典的问题...鹰蛋问题...IOI2004年的一论文就对这个问题有过深入探讨...比赛的时候我只想到了个大概...
我的思路和论文中的方法二差不多...状态的表示dp[k][p]代表在确定层数为k时用p个球所需确定鹰蛋承受能力的最小次数...也就是输入输出的东西了...我觉得这种状态时最为直观的...在更新时可以用二分..那么时间复杂度为O(n^m*logn)..有0<n,m<=1000...可以接受....
直观的例子...首先初值dp[k][1]=k...(0<k<=1000) 显而易见...如果要更新出dp[10][2]...
最优方案: 将第一个蛋在4层扔一次..若蛋碎..问题转化为dp[3][1].. 若没碎... 再将第一个蛋在7层扔一次..若此时但碎..问题转化为dp[[2][1]...若第一个蛋还没碎..再将第一个蛋在9层扔一次..若蛋碎..问题转化为dp[1][1]..若没碎..问题转化为dp[1][1]...可见由于第一个蛋的碎与没碎..将情况分类成好些...而dp[3][1]+1是最多的..为4..所以dp[10][2]=4..
那为何在第4层失败后...第二次是扔第7层..因为知道dp[3][1]=3..那么要维持最多时dp[3][1]+1=4次..那么就要保证第一个蛋扔两次后第二个蛋只能扔2次...若两次的距离为2..dp[2][1]=2...2+2=4..那么可行...4+1+2=7..同理...7+1+1=9位第二次扔1号蛋没碎后要选择的层数..因为能保证dp[1][1]=1,1+3=4..
如何确定第一次是第4层?..由于第一次扔在哪就能直接确定后面扔在哪..且第一次扔的高度与这种方案确定的次数是同单调的...如dp[100][2]一定不会大于dp[200][2]...靠2分枚举...因为如果第一次扔第k层ok...那么第一次扔k-1也一定是ok的..
再譬如要更新dp[100][3]...二分l=-1,r=100,第一次的mid=50...
尝试...将第一个蛋先扔在50..那么就要保证往后的次数为dp[49][2]+1...所以第一个蛋若再50层没碎..第二次应该到96层...为何呢..因为第一个蛋较前种情况会多扔一次..那后两个蛋只能少扔一次...要保证两次的间隙层数=dp[49][2]-1.而dp[45][2]=dp[49][2]-1..且45是满足条件最大的(dp[46][2]=dp[47][2]=dp[48][2]=dp[49][2])...如此下去..到第一个蛋扔3次时..所能覆盖的范围超出100了...得出3个蛋第一次扔在50层一定能测试出100层之内的鹰蛋极限承受层数...那么在l=-1,r=50只能继续找答案...
这样写还是会超时..小优化..若发现蛋不断增加时..次数并没有减少..就没必要还来找了..但不能出现前后相同就跳出来直接赋值..我就这里WA了好几次...我AC的程序是判断当球增加时连续5个的值相同..则跳出直接赋值...
Program:
#include<iostream>#include<stdio.h>#include<algorithm>#include<string.h>#include<math.h>#include<map>#include<queue>#include<stack>#define ll long long#define oo 1000000000#define pi acos(-1)using namespace std; int T,t,n,m,dp[1005][1005],f[1005];int main(){ int i,j,l,r,mid,k,x,h; memset(dp,0,sizeof(dp)); for (i=0;i<=1000;i++) dp[i][1]=i; for (i=1;i<=1000;i++) { memset(f,0,sizeof(f)); for (j=2;j<=1000;j++) { l=0; r=i; while (r-l>1) { mid=(r+l)/2; k=0; x=mid; while (k<i && x>0) { h=dp[x-1][j-1]; k+=x; while (x>0 && dp[x-1][j-1]==h) x--; } if (k>=i) r=mid; else l=mid; } k=dp[r-1][j-1]+1; f[k]++; if (f[k]>5) break; dp[i][j]=k; } for (;j<=1000;j++) dp[i][j]=k; } /* scanf("%d",&T); for (t=1;t<=T;t++) { scanf("%d%d%d",&m,&m,&n); printf("%d %d\n",t,dp[n][m]); } POJ OUTPUT*/ /* while (~scanf("%d%d",&m,&n)) { if (!n && !m ) break; printf("%d\n",dp[n][m]); } URAL OUTPUT*/ return 0;}
- Ural 1223 & POJ 3783 鹰蛋问题
- 约瑟夫问题 URAL 1098
- 【物理问题】URAL
- poj 2354 || URAL 1030 Titanic
- 一类数位限制倍数的BFS问题...URAL 1495,POJ 1465,HDU 4474,HDU 1226
- URAL 1409 Bishops 思维问题
- 【URAL 1223】Chernobyl’ Eagle on a Roof(传说中的DP神优化之鹰蛋)
- 【基础拓扑排序】poj 2376/ural 1022
- ural 1031. Railway Tickets | poj 2355
- POJ - 1860 URAL - 1162 Currency Exchange
- POJ 2342 URAL 1039 Anniversary Party
- POJ 1808 + Ural 1132 平方剩余
- POJ 2368|URAL 1023|Buttons|博弈论
- POJ 2352|URAL 1028|Stars|树状数组
- URAL
- 【ural】
- URAL
- URAL
- 白话经典算法系列之七 堆与堆排序
- C++时间和日期
- SD卡FAT16文件系统的学习笔记
- C语言清空输入缓冲区
- Java UI 可视化设计工具 windowbuilder 的安装
- Ural 1223 & POJ 3783 鹰蛋问题
- Android初级开发第十讲--对象传递
- FCC认证
- Windows 2008 IIS7备份、还原站点配置 appcmd命令
- 在JAVA中调用url请求,全代码,可复制
- error C2065: 'TRACE' : undeclared identifier
- Highcharts绘制饼图
- linux互斥与同步 之 顺序锁
- Android调用系统内部的下载程序下载文件(一)