大意:青蛙过河,河中有一定数量的石墩,求可能的最小步长过河。
思路:将石墩距离起始点的距离排序,然后通过二分枚举求得是否存在一个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 ;
}