洛谷P4288||bzoj3564 [SHOI2014]信号增幅仪

bzoj3564

洛谷P4288

可以旋转一下坐标轴使得x轴与长轴方向对齐,然后将所有的横坐标变为自身除以放大倍数,然后就做一个最小圆覆盖

  1 #include<cstdio>
  2 #include<algorithm>
  3 #include<cstring>
  4 #include<vector>
  5 #include<cmath>
  6 #include<ctime>
  7 using namespace std;
  8 #define fi first
  9 #define se second
 10 #define mp make_pair
 11 #define pb push_back
 12 typedef long long ll;
 13 typedef unsigned long long ull;
 14 typedef pair<int,int> pii;
 15 namespace X
 16 {
 17     const double pi=acos(-1);
 18     const double eps=1e-6;
 19     struct Point
 20     {
 21         double x,y;
 22         Point(double x=0,double y=0):x(x),y(y){}
 23     };
 24     typedef Point Vec;
 25     Vec operator+(const Vec& a,const Vec& b)
 26     {
 27         return Vec(a.x+b.x,a.y+b.y);
 28     }
 29     Vec operator-(const Vec& a,const Vec& b)
 30     {
 31         return Vec(a.x-b.x,a.y-b.y);
 32     }
 33     Vec operator*(double a,const Vec& b)
 34     {
 35         return Vec(a*b.x,a*b.y);
 36     }
 37     Vec operator*(const Vec& a,double b)
 38     {
 39         return Vec(b*a.x,b*a.y);
 40     }
 41     Vec operator/(const Vec& a,double b)
 42     {
 43         return Vec(a.x/b,a.y/b);
 44     }
 45     int dcmp(double x)
 46     //正为1,负为-1,0为0
 47     {
 48         if(fabs(x)<eps)    return 0;
 49         return x<0?-1:1;
 50     }
 51     bool operator==(const Vec& a,const Vec& b)
 52     //判向量相等
 53     {
 54         return dcmp(a.x-b.x)==0&&dcmp(a.y-b.y)==0;
 55     }
 56     double dot(const Vec& a,const Vec& b)
 57     //点积
 58     {
 59         return a.x*b.x+a.y*b.y;
 60     }
 61     double cross(const Vec& a,const Vec& b)
 62     //叉积
 63     {
 64         return a.x*b.y-a.y*b.x;
 65     }
 66     double len(const Vec& x)
 67     //向量长度
 68     {
 69         return sqrt(dot(x,x));
 70     }
 71     double angle(const Vec& a,const Vec& b)
 72     //夹角,0~180°
 73     {
 74         return acos(dot(a,b)/len(a)/len(b));
 75     }
 76     double angle1(const Vec& a,const Vec& b)
 77     //夹角,带方向,a到b逆时针为正,顺时针为负,共线为0
 78     {
 79         return acos(dot(a,b)/len(a)/len(b))*(dcmp(cross(a,b)));
 80     }
 81     Vec rotate(const Vec& a,double rad)
 82     //旋转,正为逆时针,负为顺时针
 83     {
 84         return Vec(a.x*cos(rad)-a.y*sin(rad),a.x*sin(rad)+a.y*cos(rad));
 85     }
 86     Vec normal(const Vec& x)
 87     //单位法线,左转90°后除以自身长度
 88     {
 89         double l=len(x);
 90         return Vec(-x.y/l,x.x/l);
 91     }
 92     Vec normal1(const Vec& x)
 93     //法线,不归一化
 94     {
 95         return Vec(-x.y,x.x);
 96     }
 97     Point lineline(const Point& p,const Vec& v,const Point& q,const Vec& w)
 98     //直线交点,GetLineIntersection
 99     {
100         return p+v*cross(w,p-q)/cross(v,w);
101     }
102     double ptline(const Point& p,const Point& a,const Point& b)
103     //point_to_line,点到直线距离,DistanceToLine
104     {
105         Vec v1=b-a,v2=p-a;
106         return fabs(cross(v1,v2)/len(v1));
107     }
108     double ptseg(const Point& p,const Point& a,const Point& b)
109     //point_to_segment,点到线段距离,DistanceToSegment
110     {
111         if(a==b)    return len(p-a);
112         //Vec v1=b-a,v2=a-p,v3=p-b;
113         Vec v1=b-a,v2=p-a,v3=p-b;
114         if(dcmp(dot(v1,v2))<0)    return len(v2);
115         else if(dcmp(dot(v1,v3))>0)    return len(v3);
116         else return fabs(cross(v1,v2)/len(v1));
117     }
118     double area2(const Point& a,const Point& b,const Point& c)
119     //叉积对应平行四边形的面积
120     {
121         return cross(b-a,c-a);
122     }
123     double thrarea(const Point& a,const Point& b,const Point& c)
124     //三角形面积,绝对值
125     {
126         return fabs(cross(b-a,c-a)/2);
127     }
128     bool ifpar(const Vec& a,const Vec& b)
129     //ifParallel
130     //是否共线/平行
131     {
132         return dcmp(cross(a,b))==0;
133     }
134     Point pointline(const Point& p,const Point& a,const Vec& v)
135     //点在直线上投影,GetLineProjection
136     {
137         return a+v*(dot(p-a,v)/dot(v,v));
138     }
139     double sqr(double x){return x*x;} 
140     double dis2(const Point &x,const Point &y)
141     {
142         return sqr(x.x-y.x)+sqr(x.y-y.y);
143     }
144     double len2(const Vec &x){return dot(x,x);}
145 };
146 using namespace X;
147 Point p[1000100];
148 int n;
149 Point a;
150 double r2;
151 double A,B;
152 void make(const Point &x,const Point &y)
153 {
154     Vec t=(y-x)/2;
155     a=x+t;
156     r2=len2(t);
157 }
158 void make(const Point &x,const Point &y,const Point &z)
159 {
160     Vec t1=(y-x)/2,t2=(z-y)/2;
161     Point x1=x+t1,y1=y+t2;
162     t1=normal1(t1);t2=normal1(t2);
163     a=lineline(x1,t1,y1,t2);
164     r2=dis2(a,x);
165 }
166 bool ok(const Point &x)
167 {
168     return dcmp(dis2(x,a)-r2)<=0;
169 }
170 int main()
171 {
172     int i,j,k;
173     srand(time(0));
174     scanf("%d",&n);
175     for(i=1;i<=n;i++)
176         scanf("%lf%lf",&p[i].x,&p[i].y);    
177     scanf("%lf%lf",&A,&B);A=A/180*pi;
178     for(i=1;i<=n;i++)
179         p[i]=rotate(p[i],-A);
180     for(i=1;i<=n;i++)
181         p[i].x/=B;
182     random_shuffle(p+1,p+n+1);
183     a=p[1];r2=0;
184     for(i=2;i<=n;i++)
185         if(!ok(p[i]))
186         {
187             a=p[i];r2=0;
188             for(j=1;j<i;j++)
189                 if(!ok(p[j]))
190                 {
191                     make(p[i],p[j]);
192                     for(k=1;k<j;k++)
193                         if(!ok(p[k]))
194                         {
195                             make(p[i],p[j],p[k]);
196                         }
197                 }
198         }
199     //uprintf("%.2f %.2f ",a.x,a.y);
200     printf("%.3f\n",sqrt(r2));
201     return 0;
202 }
View Code

 

posted @ 2018-10-24 15:53  hehe_54321  阅读(188)  评论(0编辑  收藏  举报
AmazingCounters.com