模拟退火 & UVA10228 A Star not a Tree?

洛谷传送门


模拟退火

推荐一篇感觉写得很好的洛谷日报


补充一点就是可以加个判断(这个题因为有多组T不适用):

while ((double)clock()/CLOCKS_PER_SEC<MAX_TIME) SA();

注意这个题的输出格式特别狗……

AC代码

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<ctime>
using namespace std;
const double delta=0.996;
int T,n;
double ans,ansx,ansy,sumx,sumy;
struct node{
	double x,y;
}a[105];
double work(double x,double y){
	double ans=0;
	for(int i=1;i<=n;i++){
		ans+=sqrt((x-a[i].x)*(x-a[i].x)+(y-a[i].y)*(y-a[i].y));
	}
	return ans;
}
void SA(){
	double t=3000,x=ansx,y=ansy;
	while(t>1e-15){
		double newx=x+(rand()*2-RAND_MAX)*t,newy=y+(rand()*2-RAND_MAX)*t;
		double res=work(newx,newy);
		double cha=res-ans;
		if(cha<0) ansx=x=newx,ansy=y=newy,ans=res;
		else{
			if(exp(-cha/t)*RAND_MAX>rand()) x=newx,y=newy;
		}
		t*=delta;
	}
}
int main(){
	ios::sync_with_stdio(false);
	srand(time(NULL));
	cin>>T;
	while(T--){
		cin>>n;
		for(int i=1;i<=n;i++){
			int x,y;
			cin>>x>>y;
			a[i].x=x;
			a[i].y=y;
			sumx+=x;
			sumy+=y;
		}
		ansx=sumx/n;
		ansy=sumy/n;
		ans=1e8;
		for(int i=1;i<=10;i++) SA();
		if(T>=1) cout<<round(ans)<<endl<<endl;
		else cout<<round(ans)<<endl;
	}
	return 0;
}
posted @ 2021-07-16 19:37  尹昱钦  阅读(29)  评论(0编辑  收藏  举报