poj 2069 Super Star —— 模拟退火

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

仍是随机地模拟退火,然而却WA了;

看看网上的题解,都是另一种做法——向距离最远的点靠近;

于是也改成那样,竟然真的A了...感觉这个做法的随机因素好像很小?不过似乎也是一种套路。

代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#include<ctime>
#define eps 1e-17
#define dt 0.997
using namespace std;
typedef double db;
int const xn=35;
int n;
db xx[xn],yy[xn],zz[xn],ans,ansx,ansy,ansz;
int rd()
{
  int ret=0,f=1; char ch=getchar();
  while(ch<'0'||ch>'9'){if(ch=='-')f=0; ch=getchar();}
  while(ch>='0'&&ch<='9')ret=(ret<<3)+(ret<<1)+ch-'0',ch=getchar();
  return f?ret:-ret;
}
db dist(db x,db y,db z,db a,db b,db c){return sqrt((x-a)*(x-a)+(y-b)*(y-b)+(z-c)*(z-c));}
db cal(db x,db y,db z)
{
  db ret=0;
  for(int i=1;i<=n;i++)ret=max(ret,dist(x,y,z,xx[i],yy[i],zz[i]));
  return ret;
}
void SA()
{
  db T=10000,x=ansx,y=ansy,z=ansz,lst=ans,tx,ty,tz,tmp;
  while(T>eps)
    {
      int id; db ret=0,tt;
      for(int i=1;i<=n;i++)
    if((tt=dist(x,y,z,xx[i],yy[i],zz[i]))>ret)ret=tt,id=i;
      ans=min(ans,ret);
      x+=(xx[id]-x)/ret*T;
      y+=(yy[id]-y)/ret*T;
      z+=(zz[id]-z)/ret*T;
      T*=dt;
    }
}
int main()
{
  srand(time(0));
  while(1)
    {
      n=rd(); if(!n)return 0; db sx=0,sy=0,sz=0;
      for(int i=1;i<=n;i++)
    scanf("%lf%lf%lf",&xx[i],&yy[i],&zz[i]),sx+=xx[i],sy+=yy[i],sz+=zz[i];
      ansx=sx/n; ansy=sy/n; ansz=sz/n;
      ans=cal(ansx,ansy,ansz);
      SA();
      printf("%.5lf\n",ans);
    }
  return 0;
}

 

posted @ 2018-10-30 17:52  Zinn  阅读(230)  评论(0编辑  收藏  举报