MnZn刚学模拟退火1ms,求调
查看原帖
MnZn刚学模拟退火1ms,求调
846661
ARIS1_0楼主2024/10/22 08:36
#include<bits/stdc++.h>
#define ll long long
using namespace std;
mt19937 myrand(time(0));
inline ll read(){
	ll x=0,w=1;
	char ch=0;
	while(ch<'0'||ch>'9'){
		if(ch=='-')w=-1;
		ch=getchar();
	}
	while(ch>='0'&&ch<='9'){
		x=(x<<3)+(x<<1)+(ch^48);
		ch=getchar();
	}
	return x*w;
}
void write(ll x){
	if(x<0){
		putchar('-');
		x=-x;
	}
	static int sta[35];
	int top=0;
	do{
		sta[top++]=x%10,x/=10;
	}while(x);
	while(top)putchar(sta[--top]+'0');
}
namespace ___{
const double delta=0.996;
int t,n;
inline int randint(int l,int r){
	return myrand()%(r-l+1)+l;
}
struct node{
	double x,y;
}a[105],ans;
double res;
double dis(double x1,double y1,double x2,double y2){
	return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
}
int calc(double x,double y){
	double ret=0;
	for(int i=1;i<=n;i++){
		ret+=dis(x,y,a[i].x,a[i].y);
	}
	return ret;
}
void SA(){
	double T=1e3;
	while(T>=1e-14){
		node now;
		now.x=ans.x+(myrand()*2%RAND_MAX)*1.0*T;
		now.y=ans.y+(myrand()*2%RAND_MAX)*1.0*T;
		if(now.x>10000||now.x<0||now.y>10000||now.y<0){
			T*=delta;
			continue;
		}
		double newdis=calc(now.x,now.y);
		if(newdis<res){
			res=newdis;
			ans=now;
		}
		T*=delta;
	}
}
void mian(){
	t=read();
	for(int CW=1;CW<=t;CW++){
		n=read();
		int sumx=0,sumy=0;
		for(int i=1;i<=n;i++){
			a[i].x=read();
			a[i].y=read();
			sumx+=a[i].x;
			sumy+=a[i].y;
		}
		ans.x=sumx/n;
		ans.y=sumy/n;
		res=calc(ans.x,ans.y);
		for(int i=1;i<=50;i++)SA();
		printf("%.0f\n",res);
		if(CW!=t)puts("");
	}
}
}
using namespace ___;
int main(){
	mian();
	return 0;
}
2024/10/22 08:36
加载中...