题目: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; }