模拟退火80pts
  • 板块P1433 吃奶酪
  • 楼主tai_chi
  • 当前回复9
  • 已保存回复9
  • 发布时间2022/11/23 21:48
  • 上次更新2023/10/27 01:46:23
查看原帖
模拟退火80pts
781046
tai_chi楼主2022/11/23 21:48

求助调参,调了 1h 了,感觉和题解的参数已经调得差不多了

#include<bits/stdc++.h>
using namespace std;
const int maxn=25;
typedef double db;
int n;
struct node{
	int x,y;
}a[maxn];
int p[maxn];//p是操作序列 
db dis(int X1,int Y1,int X2,int Y2){
	return sqrt((X1-X2)*(X1-X2)+(Y1-Y2)*(Y1-Y2));
}
bool cmp(node x,node y){
	return dis(x.x,x.y,0,0)<dis(y.x,y.y,0,0);
}
db fun(){
	db ret=0;
	for(int i=1;i<=n;i++){
		ret+=dis(a[p[i]].x,a[p[i]].y,a[p[i-1]].x,a[p[i-1]].y);
	}
	return ret;
}
db ans=100000000;
void sa(){
	db d=0.997,t=100000,eps=0.0001;
	for(int i=1;i<=n;i++)
		p[i]=i;
	while(t>eps){
		db f1=fun();ans=min(ans,f1);
		int tmp1=rand()%n+1,tmp2=rand()%n+1;//在操作序列中随机选取两个交换 
		swap(p[tmp1],p[tmp2]);
		
		db f2=fun();db df=f1-f2;
		if(df>0)
			ans=min(ans,f2);
		else if(exp(df/t)*RAND_MAX>rand()){}//接受=啥也不干 
		else 
			swap(p[tmp1],p[tmp2]);//不接受=换过的再换回来 
		t*=d;
	}
}
int main(){
	time(0);
	srand(19260817);
	cin>>n;
	a[0].x=0;a[0].y=0;
	for(int i=1;i<=n;i++)
		cin>>a[i].x>>a[i].y;
	sort(a+1,a+n+1,cmp);
	while(clock()<0.9*CLOCKS_PER_SEC)
		sa();
	cout<<fixed<<setprecision(2)<<ans<<endl;
	return 0;
}
2022/11/23 21:48
加载中...