http://poj.org/problem?id=2069
n 个点的坐标(xi,yi,zi ),求覆盖这n 个点的最小球的半径r 。
再一次见识到了模拟退火的威力。首先我们乱定一个圆心,然后退火乱搞就行了,过程比较简单。注意每次移动的变化量参数delta 最好定为0.98 ,具体为什么不清楚,但是据网上说设成0.95 精度就会出现问题。
struct Point { double x,y,z; }points[55]; int n,q; //需要被覆盖的点的个数为n, double dist(Point a,Point b) { return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)+(a.z-b.z)*(a.z-b.z)); } double getR(Point t) //求圆心为t的最小覆盖球的半径 { double tmp=0; for(int i=1;i<=n;i++) tmp=max(tmp,dist(t,points[i])); return tmp; } double SA(Point start) //模拟退火,start=最开始确定的圆心 { double ans=1e20; //答案=最小覆盖球的半径 double delta=100; //每次移动的变化量 while(delta>EPS) { int d=1; //d为离当前确定的圆心最远的点的编号 for(int i=1;i<=n;i++) if(dist(start,points[i])>dist(start,points[d])) d=i; double nowr=dist(start,points[d]); //nowr=当前固定圆心的最小覆盖球的半径大小 ans=min(ans,nowr); start.x+=(points[d].x-start.x)/nowr*delta; start.y+=(points[d].y-start.y)/nowr*delta; start.z+=(points[d].z-start.z)/nowr*delta; delta*=0.98; } return ans; } int main() { srand(time(0)); while(scanf("%d",&n)!=EOF&&n) { Point center; center.x=center.y=center.z=0; for(int i=1;i<=n;i++) { scanf("%lf%lf%lf",&points[i].x,&points[i].y,&points[i].z); center.x+=points[i].x; center.y+=points[i].y; center.z+=points[i].z; } center.x=0; center.y=0; center.z=0; /* center.x/=n; center.y/=n; center.z/=n;*/ printf("%.5lf\n",SA(center)); } return 0; }
During a voyage of the starship Hakodate-maru (see Problem 1406), researchers found strange synchronized movements of stars. Having heard these observations, Dr. Extreme proposed a theory of "super stars". Do not take this term as a description of actors or singers. It is a revolutionary theory in astronomy.
According to this theory, starts we are observing are not independent objects, but only small portions of larger objects called super stars. A super star is filled with invisible (or transparent) material, and only a number of points inside or on its surface shine. These points are observed as stars by us.
In order to verify this theory, Dr. Extreme wants to build motion equations of super stars and to compare the solutions of these equations with observed movements of stars. As the first step, he assumes that a super star is sphere-shaped, and has the smallest possible radius such that the sphere contains all given stars in or on it. This assumption makes it possible to estimate the volume of a super star, and thus its mass (the density of the invisible material is known).
You are asked to help Dr. Extreme by writing a program which, given the locations of a number of stars, finds the smallest sphere containing all of them in or on it. In this computation, you should ignore the sizes of stars. In other words, a star should be regarded as a point. You may assume the universe is a Euclidean space.
According to this theory, starts we are observing are not independent objects, but only small portions of larger objects called super stars. A super star is filled with invisible (or transparent) material, and only a number of points inside or on its surface shine. These points are observed as stars by us.
In order to verify this theory, Dr. Extreme wants to build motion equations of super stars and to compare the solutions of these equations with observed movements of stars. As the first step, he assumes that a super star is sphere-shaped, and has the smallest possible radius such that the sphere contains all given stars in or on it. This assumption makes it possible to estimate the volume of a super star, and thus its mass (the density of the invisible material is known).
You are asked to help Dr. Extreme by writing a program which, given the locations of a number of stars, finds the smallest sphere containing all of them in or on it. In this computation, you should ignore the sizes of stars. In other words, a star should be regarded as a point. You may assume the universe is a Euclidean space.
Input
The input consists of multiple data sets. Each data set is given in the following format.
n
x1 y1 z1
x2 y2 z2
. . .
xn yn zn
The first line of a data set contains an integer n, which is the number of points. It satisfies the condition 4 <= n <= 30.
The location of n points are given by three-dimensional orthogonal coordinates: (xi, yi, zi) (i = 1, ..., n). Three coordinates of a point appear in a line, separated by a space character. Each value is given by a decimal fraction, and is between 0.0 and 100.0 (both ends inclusive). Points are at least 0.01 distant from each other.
The end of the input is indicated by a line containing a zero.
n
x1 y1 z1
x2 y2 z2
. . .
xn yn zn
The first line of a data set contains an integer n, which is the number of points. It satisfies the condition 4 <= n <= 30.
The location of n points are given by three-dimensional orthogonal coordinates: (xi, yi, zi) (i = 1, ..., n). Three coordinates of a point appear in a line, separated by a space character. Each value is given by a decimal fraction, and is between 0.0 and 100.0 (both ends inclusive). Points are at least 0.01 distant from each other.
The end of the input is indicated by a line containing a zero.
Output
For each data set, the radius of the smallest sphere containing all given points should be printed, each in a separate line. The printed values should have 5 digits after the decimal point. They may not have an error greater than 0.00001.
Sample Input
4 10.00000 10.00000 10.00000 20.00000 10.00000 10.00000 20.00000 20.00000 10.00000 10.00000 20.00000 10.00000 4 10.00000 10.00000 10.00000 10.00000 50.00000 50.00000 50.00000 10.00000 50.00000 50.00000 50.00000 10.00000 0
Sample Output
7.07107 34.64102题目大意:给
再一次见识到了模拟退火的威力。首先我们乱定一个圆心,然后退火乱搞就行了,过程比较简单。注意每次移动的变化量参数
struct Point { double x,y,z; }points[55]; int n,q; //需要被覆盖的点的个数为n, double dist(Point a,Point b) { return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)+(a.z-b.z)*(a.z-b.z)); } double getR(Point t) //求圆心为t的最小覆盖球的半径 { double tmp=0; for(int i=1;i<=n;i++) tmp=max(tmp,dist(t,points[i])); return tmp; } double SA(Point start) //模拟退火,start=最开始确定的圆心 { double ans=1e20; //答案=最小覆盖球的半径 double delta=100; //每次移动的变化量 while(delta>EPS) { int d=1; //d为离当前确定的圆心最远的点的编号 for(int i=1;i<=n;i++) if(dist(start,points[i])>dist(start,points[d])) d=i; double nowr=dist(start,points[d]); //nowr=当前固定圆心的最小覆盖球的半径大小 ans=min(ans,nowr); start.x+=(points[d].x-start.x)/nowr*delta; start.y+=(points[d].y-start.y)/nowr*delta; start.z+=(points[d].z-start.z)/nowr*delta; delta*=0.98; } return ans; } int main() { srand(time(0)); while(scanf("%d",&n)!=EOF&&n) { Point center; center.x=center.y=center.z=0; for(int i=1;i<=n;i++) { scanf("%lf%lf%lf",&points[i].x,&points[i].y,&points[i].z); center.x+=points[i].x; center.y+=points[i].y; center.z+=points[i].z; } center.x=0; center.y=0; center.z=0; /* center.x/=n; center.y/=n; center.z/=n;*/ printf("%.5lf\n",SA(center)); } return 0; }