大意:青蛙过河,河中有一定数量的石墩,求可能的最小步长过河。
思路:将石墩距离起始点的距离排序,然后通过二分枚举求得是否存在一个m值(0~L),使得青蛙可以走过所有的石墩。如果存在且小于M,则记录满足条件的最小值。
小结:二分枚举的题的特点都是是否单调连续,如果题目有这个特点的话,那么就可以考虑通过二分的思想来求解。
CODE:
#include <iostream>
#include <stdio.h>
#include < string.h>
using namespace std ;
const int SIZE = 500010;
int L, N, M ;
int a[SIZE];
int cmp( const void *a, const void *b)
{
return *( int*)a - *( int*)b;
}
int check( int dis) //检查是否可以通过所有的桥墩。
{
int i, j, step ;
if(dis*M < L) return 0;
i = 1;
j = 0;
step = 0;
while(i <= N+ 1)
{
step++;
if (dis < a[i]-a[j])
return 0;
while(dis >= a[i]-a[j] && i <= N+ 1) //这儿很重要
i++;
j = i- 1; //保存当前走到的位置
}
if(step > M) return 0;
return 1;
}
int main()
{
int i, j;
int x, y, mid;
while(~scanf( " %d%d%d ", &L, &N, &M))
{
a[ 0] = 0 ;
for(i = 1; i <= N; i++) scanf( " %d ", &a[i]);
a[N+ 1] = L;
qsort(a, N+ 2, sizeof( int), cmp);
int y = L;
int x = 0;
while (x <= y)
{
mid = (x+y)/ 2;
if (check(mid))
y = mid- 1;
else
x = mid+ 1;
}
printf( " %d\n ", x);
}
return 0 ;
}
#include <stdio.h>
#include < string.h>
using namespace std ;
const int SIZE = 500010;
int L, N, M ;
int a[SIZE];
int cmp( const void *a, const void *b)
{
return *( int*)a - *( int*)b;
}
int check( int dis) //检查是否可以通过所有的桥墩。
{
int i, j, step ;
if(dis*M < L) return 0;
i = 1;
j = 0;
step = 0;
while(i <= N+ 1)
{
step++;
if (dis < a[i]-a[j])
return 0;
while(dis >= a[i]-a[j] && i <= N+ 1) //这儿很重要
i++;
j = i- 1; //保存当前走到的位置
}
if(step > M) return 0;
return 1;
}
int main()
{
int i, j;
int x, y, mid;
while(~scanf( " %d%d%d ", &L, &N, &M))
{
a[ 0] = 0 ;
for(i = 1; i <= N; i++) scanf( " %d ", &a[i]);
a[N+ 1] = L;
qsort(a, N+ 2, sizeof( int), cmp);
int y = L;
int x = 0;
while (x <= y)
{
mid = (x+y)/ 2;
if (check(mid))
y = mid- 1;
else
x = mid+ 1;
}
printf( " %d\n ", x);
}
return 0 ;
}