【模拟退火】最小球POJ 2069/codeforces 82 E

来源:互联网 发布:mac toast and butter 编辑:程序博客网 时间:2024/05/17 21:07

这两题都是大同小异,一个求最小球半径,一个求球心。方法都是用模拟退火,每次往最远距离移动,并且调整步距,计数器要取值适当,掌握不好火候就会悲剧~

下面贴poj2069,codeforces 82E差不多,改一下输入输出就过

#include <vector>#include <list>#include <map>#include <set>#include <queue>#include <string.h>#include <deque>#include <stack>#include <algorithm>#include <iostream>#include <iomanip>#include <cstdio>#include <cmath>#include <cstdlib>#include <limits.h>#include <time.h>using namespace std;#define LL long long#define PI acos(-1.0)#define N  110#define MAX INT_MAX#define MIN INT_MIN#define eps 1e-8#define FRE freopen("a.txt","r",stdin)struct node{      double x,y,z;  }p[N];  double dis(node a,node 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));}int n;  int main(){      while(scanf("%d",&n) &&n){          int i,j,k;          node p0;          p0.x=0,p0.y=0,p0.z=0;          for(i=0;i<n;i++){              scanf("%lf %lf %lf",&p[i].x,&p[i].y,&p[i].z);              p0.x+=p[i].x;              p0.y+=p[i].y;              p0.z+=p[i].z;          }          p0.x/=n;    //初始点为靠近中心的点          p0.y/=n;          p0.z/=n;          double step=0.1;          double s,t;          for(j=0;j<25000;j++){              k=0;              s=dis(p0,p[0]);              for(i=1;i<n;i++){                  t=dis(p0,p[i]);                  if(s<t){                      s=t;                      k=i;                  }              }      //往最远的点移动调整              p0.x+=(p[k].x-p0.x)*step;              p0.y+=(p[k].y-p0.y)*step;              p0.z+=(p[k].z-p0.z)*step;              step*=0.9993;          }          printf("%.5f\n",s);      }      return 0;  }