zoukankan      html  css  js  c++  java
  • 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;
    }
    
  • 相关阅读:
    POJ 2240 Arbitrage spfa 判正环
    POJ 3259 Wormholes spfa 判负环
    POJ1680 Currency Exchange SPFA判正环
    HDU5649 DZY Loves Sorting 线段树
    HDU 5648 DZY Loves Math 暴力打表
    HDU5647 DZY Loves Connecting 树形DP
    CDOJ 1071 秋实大哥下棋 线段树
    HDU5046 Airport dancing links 重复覆盖+二分
    HDU 3335 Divisibility dancing links 重复覆盖
    FZU1686 神龙的难题 dancing links 重复覆盖
  • 原文地址:https://www.cnblogs.com/gmh77/p/12392849.html
Copyright © 2011-2022 走看看