http://acm.hdu.edu.cn/showproblem.php?pid=3932
题意:给一堆点,求一个点到这些点的最远距离最小。。。精度0.1即可
分析:
此题本来是最小圆覆盖的模板题。。。我一开始就想到费马点的模拟退火去了。。花了一个下午没写出来。。。。
最开始是用4个方向的搜索判断减小步长的方式,后来改到8个方向还是不行,精度都调到10e-9都不行。。。最后改成对当前点周围很多点(貌似用了60个)进行判断精度只需要到0.1就过了。。。表示本人无法解释原因。。。
以后不敢写模拟退火了。。上次福州现场赛调了那么久的精度险过啊。。。。。有木有!!!!!
代码:
#include<iostream> #include<cmath> using namespace std; const double pi = 3.141592654; const int N=1010; struct point { double x, y; } p[N], mn, mx, mid, mid1; int n, X, Y; double ans, ans1; double dis(point a, point b) { return (a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y); } void cal(double x, double y) { int i, j; double mx=0, tmp; point tp; tp.x = x; tp.y = y; for(i=0; i<n; i++) { tmp = dis(p[i], tp); if(tmp>mx) mx = tmp; } if(ans1>mx) { ans1 = mx; mid1 = tp; } } int main() { int i, j, k; double width; while(scanf("%d%d%d", &X, &Y, &n)!=EOF) { mn.x = mn.y = 0x7fffffff; mx.x = mx.y = 0; for(i=0; i<n; i++) { scanf("%lf%lf", &p[i].x, &p[i].y); if(p[i].x<mn.x) mn.x = p[i].x; if(p[i].y<mn.y) mn.y = p[i].y; if(p[i].x>mx.x) mx.x = p[i].x; if(p[i].y>mx.y) mx.y = p[i].y; } mid.x = (mn.x+mx.x)/2; mid.y = (mn.y+mx.y)/2; mid1 = mid; width = mx.x; if(mx.y>width) width = mx.y; ans1 = 0; for(i=0; i<n; i++) { if(dis(mid, p[i])>ans1) ans1 = dis(mid, p[i]); } ans = ans1; double ii; while(1) { /* cal(mid.x-width, mid.y); //判断4个,8个方向不行。。即使精度调到10e-9 cal(mid.x+width, mid.y); cal(mid.x, mid.y-width); cal(mid.x, mid.y+width); cal(mid.x-width, mid.y-width); cal(mid.x-width, mid.y+width); cal(mid.x+width, mid.y-width); cal(mid.x+width, mid.y+width); */ for(ii=0; ii<=2*pi; ii+=0.1) //旋转对很多个点进行判断。。 { cal(mid.x+width*cos(ii), mid.y+width*sin(ii)); } if(ans-ans1<0.1 && width<0.001) break; if(ans1<ans) { ans = ans1; mid = mid1; } else width *= 0.5; } printf("(%.1lf,%.1lf).\n", mid.x, mid.y); printf("%.1lf\n", sqrt(ans)); } return 0; }