您的位置:首页 > 其它

pku3258(二分)

2010-08-11 23:29 225 查看
http://162.105.81.212/JudgeOnline/problem?id=3258

题意:有一条河长度为L,河面上有N个石头。有一奶牛从0(一岸)跳到L(另一岸),它会依次跳到每个石头上过河。现给出N个石头的坐标,问若从N中去掉M个石头,每种方案中每次跳跃中的最小次数中的最长的那个距离。

分析:一开始都没想都要用二分,最后看了牛人的解析,才知道的,下面也是根据牛人思路写的;

加入搜索答案是mid,可以从数组的a[0]开始搜索每个点,如果该点与前一个点的距离小于mid,则去掉该点,sum++,最后统计去掉了多少个点,如果大于M,则说明mid要比答案值大,去掉的点多了;所以要向下二分right = mid - 1;否则向上二分left = mid + 1;继续寻找最优解。下面是代码:

#include<iostream>
#include<algorithm>
using namespace std;
const int maxn = 50005;
int L, N, M;
int a[maxn];
bool fun(int mid)
{
int temp = 0, sum = 0, i;	//注意:temp=0,从0开始;
for(i=0; i<=N; i++)		//枚举所有点
{
if(a[i] - temp < mid)	//距离符合
{
sum++;		//统计去掉的点数
if(sum > M) return false;	///剪枝;
}
else temp = a[i];	//更新前点
}
if(sum <= M) return true;//符合要求;
else return false;
}
int main()
{
int i, j, res, left, right, mid;
scanf("%d%d%d",&L,&N,&M);
for(i=0; i<N; i++)
scanf("%d",&a[i]);
a
= L;
sort(a, a+N+1);
left = 0;	//注意:要从0开始~
right = L;
while(left <= right)
{
mid = (left + right) >> 1;
if(fun(mid))
{
res = mid;	//保存最优解;
left = mid + 1;//向上二分
}
else right = mid - 1;//向下二分
}
printf("%d/n",res);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: