【HDUOJ】4004---The Frog's Games(二分)

来源:互联网 发布:不败传说冰川网络 编辑:程序博客网 时间:2024/06/16 14:45

The Frog's GamesHDU - 4004 

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
思路分析:
(1)题意:青蛙要从岸的一边跳到另一边,最多只能跳m次,河中有n块石头,距离左岸边有固定的距离。求要使青蛙成功过河,应该具备的最小的跳跃能力。跳跃能力指的是它所能跳跃的最长的距离,那么比跳跃能力短的长度它当然就可以轻松跳过咯。
(2)思路:求最小的跳跃能力x,这个x显然在L/m和m之间,要找到具体的x,采用二分的思想。num表示所跳跃到位置的下标,最初在岸边,则num初值为0,upper_bound(p,p+n,p[num]+x)-p表示第一个大于p[num]+x的位置的下标,那么这个位置从num的位置跳x的长度是肯定跳不到的,但是前面一个肯定就可以跳到啊,所以更新num为num=upper_bound(p,p+n,p[num]+x)-p-1;(这就是用upper_bound而不是lower_bound的原因,因为如果找到一个恰好可以跳到的位置就不能再减1了。)
代码如下:
#include<cstdio>#include<cstring>#include<algorithm>#define MAX_N 500000+11using namespace std;int p[MAX_N];int L,n,m;bool Check(int x){int num=0;//num用来表示跳跃到的石头的位置 for(int i=1;i<=m;i++)//一共可以跳跃m次 {num=upper_bound(p,p+n,p[num]+x)-p-1;//表示从上一个num的位置跳跃x的距离能够到达的位置,即新的位置,新的num if(num>=n-1)//如果num>=n-1说明在m次内跳跃到了岸的另一边,就可以返回了 return true;}return false;}int main(){while(~scanf("%d%d%d",&L,&n,&m)){for(int i=1;i<=n;i++)scanf("%d",&p[i]);p[0]=0;p[n+1]=L;//将两端也加入数组 n+=2;sort(p,p+n);//将到最左端的距离按照从小到大的顺序排列,表示各石头的位置 int lb=L/m;  //最多可以跳跃m次,那么每一次跳跃最少的长度为L/m ,即为区间左端点 int ub=L;//每次跳跃最大的长度为L,即右端点 while(ub>=lb){int mid=(lb+ub)>>1;if(Check(mid))//成立说明这个跳跃长度合适,要找到最小的,就得缩小查找范围,更新区间右端点为mid-1 ub=mid-1;elselb=mid+1;//说明这个长度跳不到岸边,要长一点,所以更新区间左端点为mid+1 }printf("%d\n",lb);}return 0;}