bzoj-3564 信号增幅仪

题意:

给出平面上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;
}
时间: 2024-10-06 21:19:34

bzoj-3564 信号增幅仪的相关文章

[SHTSC 2014] 信号增幅仪

最小覆盖圆算法.看着题解半蒙半抄的搞过去了… 主要参考以下http://blog.csdn.net/acdreamers/article/details/9406735http://blog.csdn.net/lthyxy/article/details/6661250http://blog.himdd.com/archives/2666 其中有一个求外心的过程是错的…害我调了好久…还把x和y搞反…可是就算是错的我居然过了80%的数据… 仍然几个疑问: (1)最小覆盖圆算法时间复杂度的证明 (2

[BZOJ 3564] [SHOI2014] 信号增幅仪 【最小圆覆盖】

题目链接:BZOJ - 3564 题目分析 求最小椭圆覆盖,题目给定了椭圆的长轴与 x 轴正方向的夹角,给定了椭圆长轴与短轴的比值. 那么先将所有点旋转一个角度,使椭圆长轴与 x 轴平行,再将所有点的 x 坐标除以长轴与短轴的比值,然后就直接做最小圆覆盖了. 随机增量法,一定别忘了 random_shuffle . 代码 #include <iostream> #include <cstdlib> #include <cstring> #include <cstd

BZOJ 3564 SHOI 2014 信号增幅仪 坐标变换+最小圆覆盖

题目大意:给出平面上的一些点,现在让你用一个长轴与x轴成一定角度的,长轴:短轴已知的椭圆来覆盖所有的坐标,求最小的短轴长度. 思路:很明显,这个椭圆的形状和放置状态已经给出了,但是没有办法求最小拖圆覆盖啊.采用坐标变换,将椭圆变成圆.首先我们先让长轴与x轴平行,将平面上的所有点都旋转这个角度.之后只需要让所有点的x坐标除以长轴:短轴就可以了.剩下的就是最小圆覆盖了. 注:坐标旋转公式: x' = x * cos(a) - y * sin(a) y' = x * sin(a) + y * cos(

BZOJ3564 [SHOI2014]信号增幅仪

先把椭圆长轴转到x轴上,然后把x轴按照比例缩回去,于是就变成了最小圆覆盖问题,上板子...就行 1 /************************************************************** 2 Problem: 3564 3 User: rausen 4 Language: C++ 5 Result: Accepted 6 Time:256 ms 7 Memory:2380 kb 8 *************************************

bzoj 4590

4590: [Shoi2015]自动刷题机 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 860  Solved: 300[Submit][Status][Discuss] Description 曾经发明了信号增幅仪的发明家SHTSC又公开了他的新发明:自动刷题机--一种可以自动AC题目的神秘装置.自动 刷题机刷题的方式非常简单:首先会瞬间得出题目的正确做法,然后开始写程序,每秒,自动刷题机的代码生成模 块会有两种可能的结果: A.写了x行代码

BZOJ 4590: [Shoi2015]自动刷题机 二分答案

4590: [Shoi2015]自动刷题机 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 1056  Solved: 380[Submit][Status][Discuss] Description 曾经发明了信号增幅仪的发明家SHTSC又公开了他的新发明:自动刷题机--一种可以自动AC题目的神秘装置.自动 刷题机刷题的方式非常简单:首先会瞬间得出题目的正确做法,然后开始写程序,每秒,自动刷题机的代码生成模 块会有两种可能的结果: A.写了x行代

COGS2642 / Bzoj4590 [Shoi2015]自动刷题机

Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 906  Solved: 321 Description 曾经发明了信号增幅仪的发明家SHTSC又公开了他的新发明:自动刷题机--一种可以自动AC题目的神秘装置.自动 刷题机刷题的方式非常简单:首先会瞬间得出题目的正确做法,然后开始写程序,每秒,自动刷题机的代码生成模 块会有两种可能的结果: A.写了x行代码. B.心情不好,删掉了之前写的y行代码.(如果y大于当前代码长度则相当于全部删除.) 对于每

BZOJ4590 自动刷题机

SHOI2015 Description 曾经发明了信号增幅仪的发明家SHTSC又公开了他的新发明:自动刷题机--一种可以自动AC题目的神秘装置.自动 刷题机刷题的方式非常简单:首先会瞬间得出题目的正确做法,然后开始写程序,每秒,自动刷题机的代码生成模 块会有两种可能的结果: A.写了x行代码. B.心情不好,删掉了之前写的y行代码.(如果y大于当前代码长度则相当于全部删除.) 对于每个OJ所有题目,存在某个固定的长度n>0.一旦自动刷题机在某秒结束时积累了大于等于n行的代码,它就会 自动提交并

2015-4-18 经典训练1

T1:皇帝的烦恼 二分之后DP判断. 1 var v,a,b:array[0..30008] of longint; 2 n,ans,i,l,r,mid:longint; 3 function max(a,b:longint):longint; 4 begin 5 if a>b then exit(a); exit(b); 6 end; 7 function min(a,b:longint):longint; 8 begin 9 if a<b then exit(a); exit(b); 10