1328 区间贪心

主要的思路就是将这个题目转换一下去求。题目上面说,雷达只会在x轴上面,那么我们就可以去算一下大致的几种情况:

第一种,雷达全面覆盖的到。那么转换一下思路。

第二种,存在几个特殊的,比较高的位置,雷达无法覆盖,就是雷达最高为m,但是他的位置高度超过了m,所以直接输出-1.

思路就是我们可以把每一个点转换一下,看成一个圆,去思考一下。如果点可以被覆盖的到,那么圆与x轴就会相交或者相切,以半径为雷达m范围的圆。如果他们不相交,那么就是说雷达扫描不到,因为雷达只在x轴上面。

如图:

在这里我们看见了因为相交的部分不重合,所以要想在x轴上面安雷达覆盖这两个点,我们至少需要两个。

如图的思想,我们再加一个点所构成的圆。在此注明一点就是,在x轴上面的范围就是表明雷达如果要覆盖这点,那么他就必须在这个范围里面。因为二点,一必须在x轴上面,二他是以雷达范围的圆,不在就说明点与雷达的范围超过了雷达扫描的范围。

在此图,我们可以更好的看出如果,范围重合了,就说明他们可以用一个雷达去扫描得到。

最后得到的其实就是这个图了,求的就是公共覆盖的就用一点,不是公共覆盖的就开辟,把一个范围不断的缩小,缩小的区域就是共同的雷达,不在缩小的区域类,就代表着,存在一点和你不含有公共区域。

扫描二维码关注公众号,回复: 4031770 查看本文章

所以题目的思路就清晰了,先把点转化为在x轴上面的范围,求范围的话,根据数学的公式就可以求出来了。[x-根号下(r*r-y*y),x+根号下(r*r-y*y)],这个范围就可以了。最后题目就转换成了求公共覆盖范围用一个雷达,不在就新建一个雷达。

既然我要用一个圆尝试着(雷达范围,半径为r)去覆盖岛屿,那为何不以岛屿为圆心r为半径画一个圆(记为圆O),于是只要雷达在这个圆里那么这个岛屿就能被覆盖。而从前面的分析可知,雷达必然要布置在x轴上,所以雷达肯定放在圆O与x轴的那段交线区间上,如图:

所以我们可以将所有的岛屿对应的这段区间记录下来,然后以区间左界从小到大排序就行,之后从第一个区间开始,如果第二个区间与其有交集,就更新这个交集,并从队列中除去区间1,2,如果第三个区间与这个交集又有交集,那么便更新交集并除去区间3直到不满足有交集为止。然后继续模拟这个过程就行了,每模拟以此这个过程ANS++(即区间选点问题)
 

但是这道题注意浮点误差!以及sqrt(double)的使用

#include<cmath>
#include<cstdio>
#include<algorithm>
#include<iostream>
#define MAXN 1010
using namespace std;
struct node 
{
	double xl;//最左可被侦测坐标
	double xr;//最右可被侦测坐标
}island[MAXN];
int n,d,x,y,cnt,flag;
double offset;
 
bool cmp(node a,node b)
{
	return a.xl<b.xl;
}
 
int find()
{
	int num=0;
	double cur; 	//当前最右可被侦测坐标 
	cur=island[1].xr;
	num++;
	for(int i=2;i<=n;i++)
	{
		if(island[i].xl-cur>1e-6) //下个岛屿的最左坐标大于当前最右可被侦测坐标 
		{
			num++;
			cur=island[i].xr;
		}
		else
			if(island[i].xr-cur<1e-6) //下个岛屿的最右坐标小于当前最右可被侦测坐标 
			    cur=island[i].xr;
	}
	return num; 
}
 
int main()
{
    while(~scanf("%d %d",&n,&d))
    {
    	if(n==0&&d==0)break;
        flag=0;
        cnt++;
        for(int i=1;i<=n;i++)
        {
            scanf("%d %d",&x,&y);
            if(y>d)	flag=1;
            
            offset=sqrt((double)(d*d-y*y));
            
            island[i].xl=x-offset;
            island[i].xr=x+offset;
        }
        if(flag)
        {
            printf("Case %d: -1\n",cnt);
            continue;
        }
        sort(island+1,island+n+1,cmp);
        int ans=find();
        printf("Case %d: %d\n",cnt,ans);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_40061421/article/details/83278714