spoj 145 Aliens(增量法+最小包围圈)

来源:互联网 发布:网络词爸爸是什么意思 编辑:程序博客网 时间:2024/04/24 12:02

【题目大意】:给出你T个case。每个case有n个点,叫你求这个点的半径和圆心坐标,使得这个圆覆盖所有的点(n<=100000)


【解题思路】:曾经在zoj上做过一道最小圆的覆盖,但是那道题的点只有100,当初是暴力做的。显然碰到这个数据量是行不通的,我们可以采取dfs进行增量,或者利用随机重排进行增量,二者在spoj上测试的时间差距不大,网络模版testing。


【代码】:

dfs实现增量

#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#include <vector>#include <queue>#include <cmath>#include <string>#include <cctype>#include <map>#include <iomanip>                   using namespace std;                   #define eps 1e-8#define pi acos(-1.0)#define inf 1<<30#define linf 1LL<<60#define pb push_back#define lc(x) (x << 1)#define rc(x) (x << 1 | 1)#define lowbit(x) (x & (-x))#define ll long longint n;struct Point{    double x;    double y;}pt[1005];struct Traingle{    struct Point p[3];};struct Circle{    struct Point center;    double r;}ans;//计算两点距离double Dis(struct Point p, struct Point q){    double dx=p.x-q.x;    double dy=p.y-q.y;    return sqrt(dx*dx+dy*dy);}//计算三角形面积double Area(struct Traingle ct){    return fabs((ct.p[1].x-ct.p[0].x)*(ct.p[2].y-ct.p[0].y)-(ct.p[2].x-ct.p[0].x)*(ct.p[1].y-ct.p[0].y))/2.0;}//求三角形的外接圆,返回圆心和半径(存在结构体"圆"中)struct Circle CircumCircle(struct Traingle t){    struct Circle tmp;    double a,b,c,c1,c2;    double xA,yA,xB,yB,xC,yC;    a=Dis(t.p[0],t.p[1]);    b=Dis(t.p[1],t.p[2]);    c=Dis(t.p[2],t.p[0]);    //根据S = a * b * c / R / 4;求半径R    tmp.r=(a*b*c)/(Area(t)*4.0);    xA=t.p[0].x;    yA=t.p[0].y;    xB=t.p[1].x;    yB=t.p[1].y;    xC=t.p[2].x;    yC=t.p[2].y;    c1=(xA*xA+yA*yA-xB*xB-yB*yB)/2;    c2=(xA*xA+yA*yA-xC*xC-yC*yC)/2;    tmp.center.x=(c1*(yA-yC)-c2*(yA-yB))/((xA-xB)*(yA-yC)-(xA-xC)*(yA-yB));    tmp.center.y=(c1*(xA-xC)-c2*(xA-xB))/((yA-yB)*(xA-xC)-(yA-yC)*(xA-xB));    return tmp;}//确定最小包围圆struct Circle MinCircle(int num, struct Traingle ct){    struct Circle ret;    if (num==0) ret.r=0.0;    else if (num==1){        ret.center=ct.p[0];        ret.r = 0.0;    }    else if (num==2){        ret.center.x=(ct.p[0].x+ct.p[1].x)/2.0;        ret.center.y=(ct.p[0].y+ct.p[1].y)/2.0;        ret.r=Dis(ct.p[0], ct.p[1])/2.0;    }    else if(num==3) ret=CircumCircle(ct);    return ret;}//递归实现增量算法void Dfs(int x, int num, struct Traingle ct){    int i, j;    struct Point tmp;    ans = MinCircle(num, ct);    if (num==3) return;    for (i=1; i<=x; i++)        if (Dis(pt[i],ans.center)>ans.r){            ct.p[num]=pt[i];            Dfs(i-1,num+1,ct);            tmp=pt[i];            for (j=i; j>=2; j--)                pt[j]=pt[j-1];            pt[1]=tmp;        }}void Solve(int n){    struct Traingle ct;    Dfs(n,0,ct);}int main(){    int T;    cin >> T;    while (T--){        scanf("%d",&n);       if (n==0) break;        for (int i=1; i<=n; i++)            scanf("%lf %lf",&pt[i].x,&pt[i].y);        Solve(n);        printf("%.2f\n",ans.r);        printf("%.2f %.2f\n",ans.center.x,ans.center.y);    }    return 0;}

随机重排增量

#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#include <vector>#include <queue>#include <cmath>#include <string>#include <cctype>#include <map>#include <iomanip>                   using namespace std;                   #define eps 1e-10#define pi acos(-1.0)#define inf 1<<30#define linf 1LL<<60#define pb push_back#define lc(x) (x << 1)#define rc(x) (x << 1 | 1)#define lowbit(x) (x & (-x))#define ll long longconst int N=100010;int n;struct cpoint {    double x, y;}cp[N];int dcmp(double x) {    if (x < -eps) return -1; else return x > eps;}double sqr(double x) { return x * x; }double dis(cpoint p1,cpoint p2) {    return sqrt(sqr(p1.x-p2.x)+sqr(p1.y-p2.y));}void center(cpoint p0, cpoint p1, cpoint p2, cpoint &cp) { //三角形外心    double a1=p1.x-p0.x,b1=p1.y-p0.y,c1=(sqr(a1)+sqr(b1))/2;    double a2=p2.x-p0.x,b2=p2.y-p0.y,c2=(sqr(a2)+sqr(b2))/2;    double d=a1*b2-a2*b1;    cp.x=p0.x+(c1*b2-c2*b1)/d;    cp.y=p0.y+(a1*c2-a2*c1)/d;}void MinCir(cpoint cp[], int n, cpoint &c, double &r) {    random_shuffle(cp, cp + n);    c = cp[0]; r = 0;    for (int i = 1; i < n; ++i) {        if (dcmp(dis(cp[i], c) - r) <= 0) continue;        c = cp[i]; r = 0;        for (int j = 0; j < i; ++j) {            if (dcmp(dis(cp[j], c) - r) <= 0) continue;            c.x = (cp[i].x + cp[j].x) / 2;            c.y = (cp[i].y + cp[j].y) / 2;            r = dis(c, cp[j]);            for (int k = 0; k < j; ++k) {                if (dcmp(dis(cp[k], c) - r) <= 0) continue;                center(cp[i], cp[j], cp[k], c);                r = dis(c, cp[k]);            }        }    }}void solve() {    scanf("%d",&n);    for (int i=0; i<n; ++i) {        scanf("%lf%lf",&cp[i].x,&cp[i].y);    }    cpoint c;    double r;    MinCir(cp,n,c,r);    printf("%.2f\n%.2f %.2f\n",r,c.x,c.y);}int main() {    int T;    cin >> T;    while (T--) {        solve();    }    return 0;}


 

原创粉丝点击