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

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值