【POJ - 2420】A Star not a Tree?
题目大意:给出平面上的 n n n个点,你需要找出一个点,使得这个点到各点的距离和最小,并输出这个最小距离和。
这道题需要用到模拟退火算法。首先任意取一个点 ( x , y ) (x,y) (x,y),然后设置一个最高温,让温度慢慢冷却。对于每个温度,对点 ( x , y ) (x,y) (x,y)进行相应幅度的扰动,使其变为点 ( x ′ , y ′ ) (x',y') (x′,y′)。判断新的点是否比原来的点更优。如果更优则更新,如果更劣则有一定概率更新。
code
#include<iostream>
#include<stdlib.h>
#include<time.h>
#include<cstdio>
#include<cmath>
using namespace std;
int n,T=50;
long long ans;
double t0=10000,t1,t2=1e-6,k=0.98;
struct node{
double a,b;
}w[105];
double f(double x,double y){
long double re=0,tk=1;
for(int i=1;i<=n;i++){
re+=sqrt(tk*(x-w[i].a)*(x-w[i].a)+tk*(y-w[i].b)*(y-w[i].b));
}
return re;
}
double rd(double x){
return rand()*1.0/RAND_MAX*x;
}
int main()
{
srand(time(NULL));
double tx,ty,tz,x=0,y=0,z,px=0,py=0,pz;
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%lf%lf",&w[i].a,&w[i].b);
}
t1=t0;
pz=f(0,0);
while(t1>t2){
z=f(x,y);
for(int i=1;i<=T;i++){
tx=x+(rand()%2*2-1)*t1;
ty=y+(rand()%2*2-1)*t1;
if(tx<-0.01||tx>10000.01||ty<0.01||ty>10000.01) continue;
tz=f(tx,ty);
if(tz<z){
x=tx;y=ty;z=tz;
}
else{
if(rd(1)<exp((z-tz)/t1)){
x=tx;y=ty;z=tz;
}
}
if(tz<pz){
px=tx;py=ty;pz=tz;
}
}
t1=t1*k;
}
if(px<0) px=0;
if(px>10000) px=10000;
if(py<0) py=0;
if(py>10000) py=10000;
ans=f(px,py)+0.5;
printf("%lld",ans);
return 0;
}