CodeVs1344 线型网络

题面

解法:

         奇(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;
}

猜你喜欢

转载自blog.csdn.net/Bill_Benation/article/details/82050596
今日推荐