二分 青蛙游戏

题意

青蛙王国运动会开始了,最受欢迎的游戏是铁蛙三项赛,其中一项是跳跃过河项目。这个项目需要青蛙运动员通过跳跃过河。河的宽度是L。在河面上有直线排列的n个石头。青蛙可以利用这些石头跳跃过河,如果落入河中则失败。青蛙们能够跳跃的最多次数是m。现在铁蛙门想要知道他们至少需要具备多大的跳跃距离,才能够顺利完成比赛。

思路

        暑假做的一道二分题,但是好久没练习导致上机比赛时写不出来,所以来巩固一下。

        用a[ ]数组来存储这条河的每个落脚点包括两岸,并按小到大排序,用二分写法得到一个个的跳跃距离然后进行判断tofind(),如可行则缩小跳跃距离再进行判断,否则扩大进行判断直到找到最合适的跳跃距离为止。二分的思路很好理解,接下来是判断的问题。在判断函数里有一限制条件,跳跃次数是m次要在小于或等于m次跳跃中跳过这条河。所以从问题能否在有限次跳跃中跳过河,变成在跳跃距离一定情况下且跳过了河时,求最小跳跃次数是否不超过m次,如果行则返回true,否则返回false。

         在tofind()函数里ans记录步数,los是每次起跳的位置,用for循环和if的判断组合起来是每次跳mid的距离所能到达的最远的石头(地方),循环到最后其实还没有到对岸,故ans++。

code

#include<stdio.h>
#include<algorithm>
using namespace std;

int L,n,m;
int a[100];

bool tofind(int mid)
{
	int ans=0; //记录步数 
	int los=0; //每次起跳的起点位置,是a[]数组的下标值 
	
	for(int i=1;i<=n+1;i++)
	{                                                    
		if(mid>=(a[i]-a[los]) && (a[i+1]-a[los])>mid) //每次跳跃能够到达的最远距离 
		{
			ans++;
			los=i;
		}
		if(mid<(a[i]-a[los]))
		{
			return false;
		}
	} 
	ans++;
	if(ans<=m)
	{
		return true;
	}
	else
	{
		return false;
    } 
}

int main()
{	
	while(scanf("%d%d%d",&L,&n,&m)!=EOF)
	{
		a[0]=0;
		for(int i=1;i<=n;i++)
		    scanf("%d",&a[i]); // 11 2 18
		    
		a[n+1]=L;
		sort(a,a+n+1);
		
		int l,r,mid;
		l=0,r=L;
		
		while(r>=l)
		{
			mid=(r+l)/2;
			
			if(tofind(mid))
			{
				r=mid-1;
			}
			else
			{
				l=mid+1;
			}
		}
		
		printf("%d\n",l);
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/LaoXiangQ/article/details/84663404
今日推荐