题目就是说,一条长为l的河有n块石头,给出每块石头离起始的岸边的距离,要求青蛙在经过小于等于m次跳跃后就能到达彼岸,求青蛙在跳的过程中,跳的距离最长的那一步距离是多少。不妨将其称为最长距离。
显而易见,如果只跳一步的话,最长距离就是河的宽度l。取最小的最长距离为0。
利用二分的思想,每次取其中值mid,进行判断。
如果在m次内能跳到彼岸且m次跳跃的距离皆小于mid,则说明 最长距离 最小 可以为mid。
如果不能,则说明 最长距离 最小 至少要mid。
另外,判断某个距离mid是否符合要求的方法如下:
每次跳跃都尽可能的使该步跳的距离最大但小于等于mid,这样便可以达到最少的步骤走跳尽可能的远(贪心的策略)。
最后判断,到达彼岸的时候所用的步骤是否超过了m。
同时,在中途也要判断,是否有哪一步出现了:当前的立足点和下一块石头的距离大于mid。
最后,需要注意的是,数据量比较大,用cin压力会很大。
#include<iostream>
#include<stdio.h>
#include<algorithm>
using namespace std;
#define Max 500000+100
long long dis[Max];
bool check(long long l,long long n,long long m,long long d)
{
if(m*d<l)
return false;
long long pre=dis[0];
long long i=1;
long long count=0;
while(i<=n+1)
{
if(dis[i]-pre>d)
return false;
while(i<=n+1&&dis[i]-pre<=d)
i++;
count++;
pre=dis[i-1];
}
#ifdef LOCAL
printf("count:%I64d pre:%I64d\n",count,pre);
#endif
if(count<m&&l-pre<=d||count==m&&l==pre)
return true;
else
return false;
}
long long solve(long long l,long long n,long long m)
{
long long left,right,mid;
left=0;right=l;
while(left<=right)
{
mid=(right-left)/2+left;
#ifdef LOCAL
printf("L:%I64d M:%I64d R:%I64d %d\n",left,mid,right,check(l,n,m,mid));
#endif
if(check(l,n,m,mid))
right=mid-1;
else
left=mid+1;
}
return left;
}
int main()
{
#ifdef LOCAL
freopen("in.txt","r",stdin);
#endif
long long l,n,m;
while(scanf("%I64d%I64d%I64d",&l,&n,&m)>0)
{
dis[0]=0;
for(int i=1;i<=n;i++)
{
scanf("%I64d",&dis[i]);
}
dis[n+1]=l;
sort(dis,dis+n+1);
printf("%I64d\n",solve(l,n,m));
}
return 0;
}
==============
以前写的