题意:
给出平面上n个点和一个角度α,一个比值p;
求一个长轴与x轴夹角为α,长轴与短轴比值为p的椭圆,
包含了这n个点,且使半短轴最小;
题解:
本来只是上bz找找计算几何凸包啥的裸题刷刷,结果怎么碰上这么一个玄学的玩意。。。
况且这题还不用凸包;
看起来只是将圆拓展到了椭圆,但是直接按原模型乱搞似乎有些难度;
判断点和椭圆的关系需要一部转化;
两点间求椭圆,甚至三点间求椭圆都并不好搞,而且还有一个旋转的角度要考虑;
所以不能硬上,要转化模型,转化到熟悉的模型就可以搞了嘛;
将圆变成椭圆需要两步:旋转,放缩;
那么把坐标系下所有点反向旋转放缩一遍,这题就是在求最小圆覆盖了;
转化后的半短轴和圆的半径相同;
随机增量法这个。。。反正我是信了!
代码:
#include<math.h>
#include<stdio.h>
#include<string.h>
#include<algorithm>
#define N 51000
using namespace std;
const double EPS=1e-8;
const double INF=1e100;
struct Point
{
double x,y;
friend bool operator <(Point a,Point b)
{
if(fabs(a.x-b.x)<=EPS)
return a.y<b.y;
return a.x<b.x;
}
friend Point operator +(Point a,Point b)
{
return (Point){a.x+b.x,a.y+b.y};
}
friend Point operator -(Point a,Point b)
{
return (Point){a.x-b.x,a.y-b.y};
}
friend Point operator *(double a,Point b)
{
return (Point){a*b.x,a*b.y};
}
friend double operator *(Point a,Point b)
{
return a.x*b.y-b.x*a.y;
}
friend double dis(Point a,Point b)
{
return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
friend Point Rotate(Point a,double alpha)
{
return (Point){a.x*cos(alpha)-a.y*sin(alpha),a.x*sin(alpha)+a.y*cos(alpha)};
}
}a[N];
struct Line
{
Point p,v;
friend Point get_Point(Line a,Line b)
{
Point u=a.p-b.p;
double temp=(b.v*u)/(a.v*b.v);
return a.p+temp*a.v;
}
}l1,l2;
struct Circle
{
Point o;
double r;
bool Is_in(Point a)
{
if(dis(o,a)<=r+EPS)
return 1;
else
return 0;
}
}O;
int main()
{
int n,m,i,j,k;
double alpha,p;
scanf("%d",&n);
for(i=1;i<=n;i++)
scanf("%lf%lf",&a[i].x,&a[i].y);
scanf("%lf%lf",&alpha,&p);
alpha=-alpha/180*acos(-1);
for(i=1;i<=n;i++)
{
a[i]=Rotate(a[i],alpha);
a[i].x/=p;
}
random_shuffle(a+1,a+n+1);
O.o=a[1],O.r=0;
for(i=1;i<=n;i++)
{
if(O.Is_in(a[i])) continue;
O.o=(Point){(a[1].x+a[i].x)/2,(a[1].y+a[i].y)/2};
O.r=dis(O.o,a[i]);
for(j=1;j<i;j++)
{
if(O.Is_in(a[j])) continue;
O.o=(Point){(a[i].x+a[j].x)/2,(a[i].y+a[j].y)/2};
O.r=dis(O.o,a[i]);
for(k=1;k<j;k++)
{
if(O.Is_in(a[k])) continue;
l1.p=(Point){(a[i].x+a[j].x)/2,(a[i].y+a[j].y)/2};
l1.v=Rotate(a[i]-a[j],acos(-1)/2);
l2.p=(Point){(a[j].x+a[k].x)/2,(a[j].y+a[k].y)/2};
l2.v=Rotate(a[j]-a[k],acos(-1)/2);
O.o=get_Point(l1,l2);
O.r=dis(O.o,a[i]);
}
}
}
printf("%.3lf",O.r);
return 0;
}