解法:
奇(chao)妙(bu)玄(zheng)学(jing)的模拟退火算法
程序:
#include<bits/stdc++.h>
#define rep(i,j,k) for(int i=j;i<=k;i++)
using namespace std;
inline int read(){
char c=getchar();int num=0;int f=1;
while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9'){num=(num<<3)+(num<<1)+(c^48);c=getchar();}
return num*f;
}
inline void qwq(int x){
if(x>9)qwq(x/10);
putchar(x%10+'0');
}
inline void write(int x){
if(x<0){x=-x;putchar('-');}
qwq(x);putchar('\n');
}
int n;
double dist[30][30];double zb[30][3];
int temp[30];int temp2[30];
inline double dis(int a[]){
double re_value=0;
rep(i,1,n-1){
re_value+=dist[a[i]][a[i+1]];
}
return re_value;
}
inline bool O_K(double x,double y){
if(x<=0)return true;
return rand()<=exp((-x)/y)*RAND_MAX;
}
inline double SA(){
double temper=10000;
random_shuffle(temp+1,temp+n+1);
rep(i,1,n){temp2[i]=temp[i];}
double re_value=dis(temp);
while(temper>0.01){
int nop1=rand()%n+1;int nop2=rand()%n+1;
swap(temp2[nop1],temp2[nop2]);
double x=dis(temp2);double y=dis(temp);
re_value=min(re_value,min(x,y));
if(O_K(x-y,temper)){
swap(temp[nop1],temp[nop2]);
}else{
swap(temp2[nop1],temp2[nop2]);
}
temper*=0.999;
}
return re_value;
}
int main(){
n=read();
rep(i,1,n){
zb[i][1]=read();zb[i][2]=read();
temp[i]=i;temp2[i]=i;
}
rep(i,1,n){
rep(j,i+1,n){
double d1=abs(zb[i][1]-zb[j][1]);
double d2=abs(zb[i][2]-zb[j][2]);
dist[i][j]=sqrt(d1*d1+d2*d2);
dist[j][i]=dist[i][j];
}
}
double ans=INT_MAX;
int T=128;
while(T){
T--;
ans=min(ans,SA());
}
printf("%.2f\n",ans);
return 0;
}