bzoj3564: [SHOI2014]信号增幅仪

来源:互联网 发布:广州凯媒通讯 知乎 编辑:程序博客网 时间:2024/04/29 11:41
去年 上海X湖北 省选题。(去年高一还是太年轻了,椭圆什么的都不知道,直接看傻眼了) 思路还算简单,但小数不好好对待就会爆掉。。。。。。
由于是椭圆,不好求,然后又告诉了你长轴是短轴的p倍(增幅仪),长轴是个歪的,反正正面强攻是不可能的,于是要将其转化为圆来求。先转换坐标系,公式自己推一下,可能你推的和别人的不一样,比如我推出来的是y1=y*cos(a)-x*sin(a)    x1=y*sin(a)+x*cos(a),我用的tan推的。。。。。然后长轴和x轴平行了,于是把长轴缩短p倍即可,最后再求一个最小圆覆盖即可。
需要注意的是数据类型小数用long double ,输出的时候要强制转换为double,注意在求外接圆圆心时可能方法不同,数据会爆掉。。。。。。(b站样例二 45中有个坑爹的空格)

3564: [SHOI2014]信号增幅仪

Time Limit: 40 Sec  Memory Limit: 256 MB
Submit: 350  Solved: 134
[Submit][Status][Discuss]

Description

无线网络基站在理想状况下有效信号覆盖范围是个圆形。而无线基站的功耗与圆的半径的平方成正比。
现给出平面上若干网络用户的位置,请你选择一个合适的位置建设无线基站....
就在你拿起键盘准备开始敲代码的时候,你的好朋友发明家 SHTSC 突然出现了。SHTSC 刚刚完成了他的新发明——无线信号增幅仪。增幅仪能够在不增加无线基站功耗的前提下,使得有效信号的覆盖范围在某一特定方向上伸长若干倍。即:使用了增幅仪的无线基站覆盖范围是个椭圆,其功耗正比于半短轴长的平方。现给出平面上若干网络用户的位置,请你选择一个合适的位置建设无线基站,并在增幅仪的帮助下使所有的用户都能接收到信号,且无线基站的功耗最小。
注意:由于SHTSC 增幅仪的工作原理依赖地磁场,增幅的方向是恒定的。

Input

第一行一个整数:n。平面内的用户个数。
之后的 n 行每行两个整数 x, y,表示一个用户的位置。
第 n+2 行一个整数:a。表示增幅仪的增幅方向,单位是度。表示增幅仪的方向是从 x 正方向逆时针转 a 度。
第 n+3 行一个整数:p。表示增幅仪的放大倍数。

Output

输出一行一个实数,为能够覆盖所有用户的最小椭圆的半短轴长,四舍五入到三位小数。

Sample Input

样例一:
2
1 0
-1 0
0
2
样例二:
3
1 1
-1 -1
0 0
45
7 





c++

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<vector>
#include<cstring>
#include<cmath>
using namespace std;
const double eps=1e-8; 
const long double pi=acos(-1);
struct Point{
long double x,y;
Point(long double x = 0, long double y = 0) : x(x), y(y) {}
};

Point operator + (Point a, Point b) {
return Point(a.x + b.x, a.y + b.y);
}

Point operator - (Point a, Point b) {
return Point(a.x - b.x, a.y - b.y);
}

Point operator * (long double k, Point a) {
return Point(a.x * k, a.y * k);
}

Point operator / (Point a, long double k) {
return Point(a.x / k, a.y / k);
}

long double dot (Point a, Point b) {
return a.x * b.x + a.y * b.y;
}

long double det (Point a, Point b) {
return a.x * b.y - a.y * b.x;
}




int n,a4,p1;
Point d[510000],c;
long double a,p,r;

long double dist(Point x,Point y)
{
return sqrt((x.x-y.x)*(x.x-y.x)+(x.y-y.y)*(x.y-y.y));
}

void zhuanhuan(int i)
{
long double x1,y1;
x1=d[i].y*sin(a)+d[i].x*cos(a);
y1=d[i].y*cos(a)-d[i].x*sin(a);
d[i].x=x1/p;
d[i].y=y1;
return ;
}
Point center(Point a, Point b, Point c) {
long double d1 = -dot(b - a, a - c), d2 = -dot(c - b, b - a), d3 = -dot(a - c, c - b);
long double c1 = d2 * d3, c2 = d3 * d1, c3 = d1 * d2, s = c1 + c2 + c3;
return ((c2 + c3) * a + (c3 + c1) * b + (c1 + c2) * c) / 2 / s;
}


void mincircle()
{
c=d[0]; r=0;
for (int i=1;i<n;i++)
{
if (dist(d[i],c)>r+eps)
{
c=d[i]; r=0;
for (int j=0;j<i;j++)
{
if (dist(d[j],c)>r+eps)
{
c.x=(d[j].x+d[i].x)/2;
c.y=(d[j].y+d[i].y)/2;
r=dist(c,d[j]);
for (int k=0;k<j;k++)
{
if (dist(d[k],c)>r+eps)
{
c=center(d[i],d[j],d[k]);
//printf("%.3lf %.3lf\n",(double)c.x,(double)c.y);
r=dist(c,d[j]);
}
}
}
}
}
}
return ;
}

int main()
{
freopen("amplifier.in","r",stdin);
freopen("amplifier.out","w",stdout);
scanf("%d",&n);
double x,y;
for (int i=0;i<n;i++)  
{
scanf("%lf%lf",&x,&y);
d[i].x=(long double)x;
d[i].y=(long double)y;
}
scanf("%d%d",&a4,&p1);
a=(long double) a4;
p=(long double) p1;
a=a*pi/180; 
for (int i=0;i<n;i++) zhuanhuan(i); 
random_shuffle(d,d+n);
mincircle();
printf("%.3lf\n", (double)r);
return 0;
}
 

0 0
原创粉丝点击