暑期集训之The Frog's Games

来源:互联网 发布:淘宝万象客服 编辑:程序博客网 时间:2024/05/22 03:42

The annual Games in frogs' kingdom started again. The most famous game is the Ironfrog Triathlon. One test in the Ironfrog Triathlon is jumping. This project requires the frog athletes to jump over the river. The width of the river is L (1<= L <= 1000000000). There are n (0<= n <= 500000) stones lined up in a straight line from one side to the other side of the river. The frogs can only jump through the river, but they can land on the stones. If they fall into the river, they 
are out. The frogs was asked to jump at most m (1<= m <= n+1) times. Now the frogs want to know if they want to jump across the river, at least what ability should they have. (That is the frog's longest jump distance).
Input
The input contains several cases. The first line of each case contains three positive integer L, n, and m. 
Then n lines follow. Each stands for the distance from the starting banks to the nth stone, two stone appear in one place is impossible.
Output
For each case, output a integer standing for the frog's ability at least they should have.
Sample Input
6 1 2225 3 311 218
Sample Output
411

哇,其实做出这道题的时候激动地不行,数据正确的时候也是很开心,因为这道题是我学完二分后的第一道完全自己做出来的题哦0~0,花了不少时间想原理,尝试性的用二分最后竟然成功了,不过提交上去一直是运行时间错误,开始的时候我一直以为是时间超限,所以疯狂看代码,看哪里需要简化,但发现自己没那个能力,无奈之下就准备放弃自己的代码了,想着写博客的时候当个反面教材算了,谁知道在看同学博客的时候意外的发现他的运行也有错误,所以我就向他请教,于是乎我就知道了我的代码并不是时间超限,而是运行时间错误,简单来说就是数组开小了,或者就是指针指错地方了,于是乎我就按着同学的数组把自己的也改了,最后竟然正确了,虽然我知道自己的思路是正确的,但代码过于繁琐所以以为超限很正常,所以现在就还有点小激动了0.0,当然,这只是一个开始,嘻嘻(*^__^*) 嘻嘻……,话不多说,代码如下,没有代码没办法解释的很清楚,所以解释都在代码的注释里面写着:

#include<stdio.h>#include<algorithm>using namespace std;int c,n,m,p;int a[1000010];//这个是每个石头距离开始地点的距离 int cal(int b)//这个子函数很长,对,就是很长,其实这个跟我的思路有关吧,思路不同这里判断也就不同了 {   int st=0;//一个起始点变量,用来储存每次的起始位置     int ans=0;//用来记录青蛙跳的次数  if(n==1)//这个的意思是如果只有一块石头的话就执行下面操作,很好理解     {   if(c<=b)        return 1;    else if(a[0]<=b&&b>=(c-a[0]))    return 2;    else    return m+1;//下面也有这个操作,所以在这里先说一下,这里的返回值是为了在无法跳过河的情况下时让下面模板里面的判断条件为假 }else//下面就是当n大于1的时候的情况了 {    for(int i=0;i<n;i++){   if(i==n-1)//这里的意思是为了考虑最后一个点和河的终点的距离问题,不好表达清楚,但你可以自己画一个图来观察一下这里的意思(结合着我下面的分析情况来看)    {     if(c-st<=b)//如果河到最后记录的起始位置的距离小于此时的跳跃距离时跳跃的步数加1     ans++;  else if(a[i]-st<=b&&c-st>b) {st=a[i];ans+=2;}else if(a[i]-st>b){ans=0;break;}   }else {if(a[i]-st<=b&&a[i+1]-st>b)//这里的意思是从河的起始点开始每次都拿距离最近的石头减去起始点的值得到的数据和此时的跳跃距离作对比,如果符合这种情况,那么跳的步数加1 {    st=a[i]; ans++;}else if(a[i]-st>b)//这里的意思是如果在跳的时候有个石头跳不过去,那么个跳跃距离b也就不符合题意,需要舍去,所以让步数归零,下面会判断 {   ans=0;break;}}    }    if(ans==0)    return m+1;//这里的意思就是如果步数在上面的一种情况下归零了,证明这个跳跃距离时不符合情况的,放回一个值,让模板里面的判断语句不成立     else    return ans;//否则的话返回正常步数(当然,这里虽然有步数,但题目中有限制步数的变量所以还需要做一个比较) }}int main(){while(scanf("%d%d%d",&c,&n,&m)!=EOF){for(int i=0;i<n;i++){scanf("%d",&a[i]);    }sort(a,a+n);//把石头按着距离远近排个序,从距离最小的开始排 int l=0;//左界限 int r=c;//右界限 while(l<=r)//这里也是经典的二分模板 只需要把其中条件改一下就好,不过条件也不简单,下面我会详细解释上面那个子函数 {int mid=(r+l)/2;if(cal(mid)<=m){    p=mid;r=mid-1;}elsel=mid+1;}printf("%d\n",l);//具体到模板里的内容也不好解释,不懂的话可以自己去查一下二分法的原理,看完你也就懂了啥意思了 }return 0; } 

怎么说,这次的题虽然是自己做出来的,但解释起来确实挺费劲的,并且我也不敢保证你一定看懂了,但我觉得看完我这个估计你会产生一点思路,总的来说,想起来的东西要表达清楚的话确实不简单,希望你们能看懂吧(说的其实够详细了,有些句子有点拗口,但感觉还是能理解的QAQ)



原创粉丝点击