• 6489. 【GDOI2020模拟02.29】守卫疆域guard


    题目描述


    题解

    感觉枚举两个点之后二分半径不满足二分性,因此枚举了两个点之后对于剩下的点找圆心在这两个点的中垂线上的区间

    然后常数就炸了(


    二分答案,枚举一个在边界上的点,考虑把圆绕着该点转一圈

    那么对于其他的点就可以表示成一个区间,在区间内会被计算到

    排序判断即可,注意判断完全碰不到的情况

    code

    #include <bits/stdc++.h>
    #define fo(a,b,c) for (a=b; a<=c; a++)
    #define fd(a,b,c) for (a=b; a>=c; a--)
    #define abs(x) ((x)>0?(x):-(x))
    #define sqr(x) ((x)*(x))
    #define inf 2133333333
    #define E 0.000000001
    #define ll long long
    #define file
    using namespace std;
    
    struct type{
    	double x,y;
    } a[501];
    struct Type{
    	double x;
    	int s;
    } b[2001];
    int n,m,i,j,k,l,tot;
    double L,R,Mid,ans,dis;
    
    bool cmp(Type a,Type b) {return abs(a.x-b.x)>E && a.x<b.x || abs(a.x-b.x)<=E && a.s>b.s;}
    
    void add(double t1,double t2)
    {
    	b[++tot]={t1,1};
    	b[++tot]={t2,-1};
    }
    
    bool pd(double R)
    {
    	int i,j,k,l,sum;
    	double dis,theta,theta2;
    	
    	fo(i,1,n)
    	{
    		sum=tot=0;
    		
    		fo(j,1,n)
    		{
    			dis=sqrt(sqr(a[i].x-a[j].x)+sqr(a[i].y-a[j].y));
    			
    			if (dis<=E)
    			++sum;
    			else
    			if (R*2>=dis)
    			{
    				theta=atan2(a[j].y-a[i].y,a[j].x-a[i].x);
    				theta2=acos(dis/(R*2));
    				if (theta<0) theta+=M_PI*2;
    				
    				if (theta-theta2<0)
    				add(theta-theta2+M_PI*2,M_PI*2),add(0,theta+theta2);
    				else
    				if (theta+theta2>M_PI*2)
    				add(theta-theta2,M_PI*2),add(0,theta+theta2-M_PI*2);
    				else
    				add(theta-theta2,theta+theta2);
    			}
    		}
    		
    		if (!tot)
    		{
    			if (sum>=m)
    			return 1;
    			continue;
    		}
    		if (sum+tot/2<m) continue;
    		
    		stable_sort(b+1,b+tot+1,cmp);
    		
    		fo(j,1,tot)
    		{
    			sum+=b[j].s;
    			if (sum>=m) return 1;
    		}
    	}
    	
    	return 0;
    }
    
    int main()
    {
    	freopen("guard.in","r",stdin);
    	#ifdef file
    	freopen("guard.out","w",stdout);
    	#endif
    	
    	scanf("%d%d",&n,&m);
    	fo(i,1,n)
    	scanf("%lf%lf",&a[i].x,&a[i].y);
    	
    	if (m==1)
    	{
    		printf("0
    ");
    		return 0;
    	}
    	else
    	if (m==2)
    	{
    		ans=inf;
    		fo(i,1,n-1)
    		{
    			fo(j,i+1,n)
    			{
    				dis=sqrt(sqr(a[i].x-a[j].x)+sqr(a[i].y-a[j].y));
    				ans=min(ans,dis/2);
    			}
    		}
    		
    		printf("%.10lf
    ",ans);
    		return 0;
    	}
    	
    	L=0;
    	R=7072;
    	while (R-L>0.0001)
    	{
    		Mid=(L+R)/2;
    		
    		if (!pd(Mid))
    		L=Mid;
    		else
    		R=Mid;
    	}
    	
    	printf("%.10lf
    ",L);
    	
    	fclose(stdin);
    	fclose(stdout);
    	
    	return 0;
    }
    
  • 相关阅读:
    人生无常 淡然处之
    对PHP开发的认知
    专家路线
    很少接触的文学
    懒加载
    Markdown入门 学习
    (转载)iOS开发历程书籍推荐
    ObjectiveC1基础代码——类和对象
    day11基础代码——函数指针
    day6
  • 原文地址:https://www.cnblogs.com/gmh77/p/12392849.html
Copyright © 2020-2023  润新知