[poj][3285][Point of view in Flatland]

题目:http://poj.org/problem?id=3285

题意:求一个与三个圆的角直径都相等并且最大的点的位置。即为求一个点,使这个点到三个圆的距离与该圆的距离之比相等。用方差的方法来进行评估随机化的结果。然后注意要确保点在范围内。

View Code
#include <cstdio>

#include <cstdlib>

#include <cmath>

#include <ctime>

#include <algorithm>



#define dis(a,b) sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y))

using namespace std;



const double pi = acos(-1.0);

const double eps = 1e-8;

const double M = 1e99;



double xx, yy, ag, e, ne, mx, my, nx, ny;

struct circle{

    double x, y, r;

    circle(){}

    circle(double x, double y):x(x),y(y){}

    void get(){ scanf("%lf%lf%lf", &x,&y,&r); xx+=x,yy+=y;}

    bool zero() { return x==0&&y==0&&r==0; }

}c[3];



void init(){

    srand(time(NULL));

    mx=-M, my=-M, nx=M, ny=M;

    for (int i=0; i<3; i++){

        mx = max(mx, c[i].x), my = max(my, c[i].y);

        nx = min(nx, c[i].x), ny = min(ny, c[i].y);

    }

    ag = max(mx-nx, my-ny);

}



double cal(circle tmp){

    if (tmp.x < nx || tmp.x > mx) return 1e99;

    if (tmp.y < ny || tmp.y > my) return 1e99;

    double r[3], a=0, ans=0;

    for (int i=0; i<3; i++)

        r[i] = c[i].r / dis(tmp,c[i]), a+=r[i];

    for (int i=0; i<3; i++)

        ans += (r[i]-a/3)*(r[i]-a/3);

    return sqrt(ans/3);

}

int main(){

    //freopen("D:/a.txt", "r", stdin);

    while (true){

        xx = yy = 0;

        for (int i=0; i<3; i++) c[i].get();

        if (c[0].zero()&&c[1].zero()&&c[2].zero()) break;

        circle p(xx/3,yy/3);

        e = cal(p);

        init();

        for (double t=ag; t>eps; t*=0.88){

            for (int k=0; k<20; k++){

                double delta = rand();

                circle tmp(p.x+cos(delta)*t,p.y+sin(delta)*t);

                ne = cal(tmp);

                if (e > ne) p=tmp, e=ne;

            }

        }

        if(e<eps) printf("%.2f %.2f\n", p.x, p.y);

        else printf("No solution\n");

    }

    return 0;

}

你可能感兴趣的:(view)