poj 2420 模拟退火法基础

/*
题意:给n个电脑,求一个点到这n个电脑的距离和最小。
模拟退火法:和poj1379的方法类似
因为坐标范围是0-10000
不妨把它看成是10000*10000的正方形来做
*/
#include<stdio.h>
#include<math.h>
#include<iostream>
#include<algorithm>
#define inf 10000000000000
using namespace std;
#define N  110
#define eps 0.1
#define pi  acos(-1.0)
struct node {
double x,y,dis;
}f[N],ff[N];
int n;
double dd,x,y;
double diss(double x,double y) {
  double sum=0;
  int i;
  for(i=1;i<=n;i++)
    sum=sum+sqrt((x-f[i].x)*(x-f[i].x)+(y-f[i].y)*(y-f[i].y));
  return sum;
}
void slove() {
  int i,j;
  double xx,yy;
  for(i=1;i<=20;i++) {
    ff[i].x=rand()%10000*1.0+1;
    ff[i].y=rand()%10000*1.0+1;
    ff[i].dis=diss(ff[i].x,ff[i].y);
  }
  double T=10000.0*sqrt(2.0);
  double rate=0.9;
  while(T>eps) {
    for(i=1;i<=20;i++)
    for(j=1;j<=30;j++) {
       double ran=(rand()%1000+1)/1000.0*pi*10;
        xx=ff[i].x+cos(ran)*T;
        yy=ff[i].y+sin(ran)*T;
        double dis=diss(xx,yy);
        if(xx<0.0||xx>10000.0||yy<0.0||yy>10000.0)continue;
        if(dis<ff[i].dis)
        ff[i].dis=dis;
    }
    T*=rate;
  }
  dd=inf;
  for(i=1;i<=20;i++){
    if(dd>ff[i].dis)
    dd=ff[i].dis;
  }
return ;
}
int main() {
    int  i;
    while(scanf("%d",&n)!=EOF) {
            x=inf;
            y=-1;
         for(i=1;i<=n;i++)
            scanf("%lf%lf",&f[i].x,&f[i].y);
         slove();
         printf("%.0f\n",dd);
    }
    return 0;
}

posted @ 2014-09-23 10:44  HYDhyd  阅读(145)  评论(0编辑  收藏  举报