【BZOJ-1336&1337】Alie最小圆覆盖 最小圆覆盖(随机增量法)

1336: [Balkan2002]Alien最小圆覆盖

Time Limit: 1 Sec  Memory Limit: 162 MBSec  Special Judge
Submit: 1573  Solved: 697
[Submit][Status][Discuss]

Description

给出N个点,让你画一个最小的包含所有点的圆。

Input

先给出点的个数N,2<=N<=100000,再给出坐标Xi,Yi.(-10000.0<=xi,yi<=10000.0)

Output

输出圆的半径,及圆心的坐标

Sample Input

6
8.0 9.0
4.0 7.5
1.0 2.0
5.1 8.7
9.0 2.0
4.5 1.0

Sample Output

5.00
5.00 5.00

HINT

Source

1337: 最小圆覆盖

Time Limit: 1 Sec  Memory Limit: 64 MB
Submit: 897  Solved: 437
[Submit][Status][Discuss]

Description

给出平面上N个点,N<=10^5.请求出一个半径最小的圆覆盖住所有的点

Input

第一行给出数字N,现在N行,每行两个实数x,y表示其坐标.

Output

输出最小半径,输出保留三位小数.

Sample Input

4
1 0
0 1
0 -1
-1 0

Sample Output

1.000

HINT

Source

Solution

最小圆覆盖裸题,随机增量法

这道题有个需要注意的地方,输出的时候不要只输出2位小数,可能会WA,可以考虑直接输出

直接把课件黏上来= =

Code

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<set>
#include<stack>
#include<cstdlib>
#include<string>
#include<bitset>
#include<iomanip>
#define INF 1000000000
#define fi first
#define se second
#define N 100005
#define MP(x,y) make_pair(x,y)
using namespace std;
typedef long long LL;
typedef pair<int,int> pii;
typedef long double Double;

struct Vector
{
    double x,y;
    Vector(double X=0,double Y=0) {x=X,y=Y;}
};
typedef Vector Point;
typedef vector<Point> Polygon;
const double eps=1e-12;
const double pi=acos(-1.0);
struct Line
{
    Point P;
    Vector v;
    double ang;
    Line() {}
    Line(Point P,Vector v):P(P),v(v) {ang=atan2(v.y,v.x);}
    bool operator<(const Line &L) const {return ang<L.ang;}
};
int dcmp(double x) {if(fabs(x)<eps) return 0; else return x<0? -1:1;}
Vector operator + (Vector A,Vector B) {return ((Vector){A.x+B.x,A.y+B.y});}
Vector operator - (Vector A,Vector B) {return ((Vector){A.x-B.x,A.y-B.y});}
Vector operator * (Vector A,double p) {return ((Vector){A.x*p,A.y*p});}
Vector operator / (Vector A,double p) {return ((Vector){A.x/p,A.y/p});}
bool operator < (const Vector& a,const Vector& b) {return a.x<b.x||(a.x==b.x&&a.y<b.y);}
bool operator == (const Vector& a,const Vector& b) {return dcmp(a.x-b.x)==0&&dcmp(a.y-b.y)==0;}
double Dot(Vector A,Vector B) {return A.x*B.x+A.y*B.y;}
double Len(Vector A) {return sqrt(Dot(A,A));}
double Cross(Vector A,Vector B) {return A.x*B.y-A.y*B.x;}
Vector Rotate(Vector A,double rad) {return ((Vector){A.x*cos(rad)-A.y*sin(rad), A.x*sin(rad)+A.y*cos(rad)});}
Point GLI(Point P,Vector v,Point Q,Vector w) {Vector u=P-Q; double t=Cross(w,u)/Cross(v,w); return P+v*t;}
Point GLI(Line a,Line b) {Vector u=a.P-b.P; double t=Cross(b.v,u)/Cross(a.v,b.v);return a.P+a.v*t;}
Point Center_of_gravity(Point A,Point B,Point C)
{
    Point P=(A+B)/2,Q=(A+C)/2;
    Vector v=Rotate(B-A,pi/2),w=Rotate(C-A,pi/2);
    if(dcmp(Len(Cross(v,w)))==0)//这是三点一线的情况
    {
        if(dcmp(Len(A-B)+Len(B-C)-Len(A-C))==0)
            return (A+C)/2;
        if(dcmp(Len(A-C)+Len(B-C)-Len(A-B))==0)
            return (A+B)/2;
        if(dcmp(Len(A-B)+Len(A-C)-Len(B-C))==0)
            return (B+C)/2;
    }
    return GLI(P,v,Q,w);
}
double Min_Cover_Circle(Point *p,int n,Point &c)
{
    random_shuffle(p,p+n);
    c=p[0];
    double r=0;
    int i,j,k;
    for(i=1;i<n;i++)
        if(dcmp(Len(c-p[i])-r)>0)
        {
            c=p[i],r=0;
            for(j=0;j<i;j++)
                if(dcmp(Len(c-p[j])-r)>0)
                {
                    c=(p[i]+p[j])/2;
                    r=Len(c-p[i]);
                    for(k=0;k<j;k++)
                        if(dcmp(Len(c-p[k])-r)>0)
                        {
                            c=Center_of_gravity(p[i],p[j],p[k]);
                            r=Len(c-p[i]);
                        }
                }
        }
    return r;
}
#define MAXN 100010
Point Po[MAXN];
int main()
{
    srand(20000104);
    int n; scanf("%d",&n);
    for (int i=1; i<=n; i++)
        {
            double x,y; scanf("%lf%lf",&x,&y);
            Po[i-1]=Point(x,y);
        }
    Point c;
    printf("%lf\n",Min_Cover_Circle(Po,n,c));
    printf("%lf %lf",c.x,c.y);
    return 0;
}
时间: 2024-10-13 12:17:39

【BZOJ-1336&1337】Alie最小圆覆盖 最小圆覆盖(随机增量法)的相关文章

Bzoj 1336&amp;1337 Alien最小圆覆盖

1336: [Balkan2002]Alien最小圆覆盖 Time Limit: 1 Sec  Memory Limit: 162 MBSec  Special Judge Submit: 1473  Solved: 648 [Submit][Status][Discuss] Description Input 先给出点的个数N,2<=N<=100000,再给出坐标Xi,Yi.(-10000.0<=xi,yi<=10000.0) Output Sample Input 6 8.0

BZOJ 1336 Balkan2002 Alien最小圆覆盖 随机增量法

题目大意:求最小圆覆盖 随机增量法裸题 注意多输出几位小数不然过不去= = #include <cmath> #include <cstdio> #include <cstring> #include <iomanip> #include <iostream> #include <algorithm> #define M 100100 #define EPS 1e-7 using namespace std; struct Point

【bzoj1336/1337/2823】[Balkan2002]Alien最小圆覆盖 随机增量法

题目描述 给出N个点,让你画一个最小的包含所有点的圆. 输入 先给出点的个数N,2<=N<=100000,再给出坐标Xi,Yi.(-10000.0<=xi,yi<=10000.0) 输出 输出圆的半径,及圆心的坐标 样例输入 6 8.0 9.0 4.0 7.5 1.0 2.0 5.1 8.7 9.0 2.0 4.5 1.0 样例输出 5.00 5.00 5.00 题解 随机增量法求最小圆覆盖裸题 求法:设初始圆为某空圆,先枚举第一个点,如果不在当前圆内,则令当前圆为这一个点的最小圆

【BZOJ1336】[Balkan2002]Alien最小圆覆盖 随机增量法

[BZOJ1336][Balkan2002]Alien最小圆覆盖 Description 给出N个点,让你画一个最小的包含所有点的圆. Input 先给出点的个数N,2<=N<=100000,再给出坐标Xi,Yi.(-10000.0<=xi,yi<=10000.0) Output 输出圆的半径,及圆心的坐标 Sample Input 6 8.0 9.0 4.0 7.5 1.0 2.0 5.1 8.7 9.0 2.0 4.5 1.0 Sample Output 5.00 5.00 5

BZOJ 1337 最小圆覆盖 随机增量法

题意:链接 方法:随机增量法 解析: 首先把所有点打乱. 然后枚举第一个点,如果不在当前的圆内则把它设为圆心. 再枚举第二个点,如果不在当前的圆内则把圆设为其与第一个点的距离为直径的圆. 再枚举第三个点,如果不在当前的圆内则把圆设为这三个点构成三角形的外接圆. 然后最后就是答案了. 别问我这为什么是对的- -! 复杂度期望O(n),我是信了. 代码: #include <cmath> #include <cstdio> #include <iomanip> #inclu

hdu 3007【最小圆覆盖-随机增量法】

#include<iostream> #include<cstdio> #include<cmath> #include<algorithm> using namespace std; const int N=505; int n; double r; struct dian { double x,y; dian(double X=0,double Y=0) { x=X,y=Y; } dian operator + (const dian &a) c

BZOJ 2280 Poi2011 Plot 二分答案+随机增量法

题目大意:给定n个点,要求分成m段,使每段最小覆盖圆半径的最大值最小 二分答案,然后验证的时候把点一个个塞进最小覆盖圆中,若半径超了就分成一块-- 等等你在跟我说不随机化的随机增量法? 好吧 那么对于一个点pos,我们要计算最大的bound满足[pos,bound]区间内的最小覆盖圆半径不超过二分的值 直接上二分是不可取的,因为我们要求m次,如果每次都验证一遍[1,n/2]直接就炸了 我们可以这么搞 首先判断[pos,pos+1-1]是否满足要求 然后判断[pos,pos+2-1]是否满足要求

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

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

HDOJ 3007 Buried memory 增量法最小圆覆盖

增量法最小圆覆盖,简单模版 Buried memory Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 2541    Accepted Submission(s): 1365 Problem Description Each person had do something foolish along with his or her g