poj1328 快排+贪心

正解思路:
    相对原点而言,我们假定x负半周方向为“左”,x正半轴方向为“右”。 
    我们找一个岛屿能被侦测到的极限范围,在雷达侦测区(圆)的左半圆上或者在雷达侦测区(圆)的右半圆上,换句话说当岛屿到雷达的距离等于d时,
    雷达可以位于岛屿的左侧也可以位于雷达的右侧。而这就可以分别确定雷达相对与岛屿x的最左坐标和x最右坐标。
    最左为:x - sqrt(d*d-y*y); 最右为:x + sqrt(d*d-y*y); 
    每个岛屿都有这样的最左和最右可被侦测坐标。
    根据贪婪的思想,每次都应该将最右可被侦测坐标作为衡量标准。
    假定当前的岛屿为cur,当前的下一个为next。
      1.如果next的最左可被侦测坐标比cur的最右都大的话,只能再设一个雷达来侦测next了。
      2.如果next的最左可被侦测坐标比cur的最右小,这时会有两种情况。
          A.next最右 < cur最右
         B.next最右 >= cur最右
         对于B情况,我们可以直接侦测到next了, 可以找next的next了.
         对于A情况,也就等价于next包含于cur, 这样就应该把next的右最为衡量标准了.
        因为这样可以左移最右坐标, 可以让可能更多的岛屿被侦测到(他们的最左与衡量标准有更多的交集)
        具体实现看代码 

#include <math.h>
#include <stdio.h>
#include <stdlib.h>
typedef struct
{
	double d1;
	double d2;
}coordinate;
coordinate island[1001]={0};
int cmp(const void*a,const void *b)
{
	if((*(coordinate *)a).d1>(*(coordinate *)b).d1)
		return 1;
	else
		return -1;

}
int greedy(coordinate island[],int n,int d)
{
	int i,num=1;
	double cur;
	cur=island[0].d2;
	for(i=1;i<n;i++)
	{
		if(island[i].d1-cur>1e-5) 
		{
			num++;
			cur=island[i].d2;
		}
		else 
		{
			if(island[i].d2-cur<1e-5)
				cur=island[i].d2;
		}
	}
	return num;
}
int main()
{
	int n,d,x,y,flag=0,i,count=0;
	double offset;
	while(scanf("%d %d",&n,&d)==2&&(n!=0&&d!=0))
	{	
		count++;
		flag=0;
		for(i=0;i<n;i++)
		{
			scanf("%d %d",&x,&y);
			if(y>d) flag=1;
			offset=sqrt(double(d*d-y*y));
			island[i].d1=x-offset;
			island[i].d2=x+offset;
			
		}
		if(flag>0)
		{
			printf("Case %d: -1\n",count);
			continue;
		}
		qsort(island,n,sizeof(island[0]),cmp);
	//	for(i=0;i<n;i++)
	//	printf("%f %f\n",island[i].d1,island[i].d2);
		i=greedy(island,n,d);
		printf("Case %d: %d\n",count,i);
	}
	return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值