MnZn刚学退火一年,有些不理解
  • 板块学术版
  • 楼主ARIS1_0
  • 当前回复1
  • 已保存回复1
  • 发布时间2024/10/17 17:34
  • 上次更新2024/10/17 18:18:00
查看原帖
MnZn刚学退火一年,有些不理解
846661
ARIS1_0楼主2024/10/17 17:34

P6505

用 SA 写过去了,但是有些不理解

去年写这道题的时候,用了概率转移方程,结果最高分只有 10pts

今年再来写的时候,把概率转移给注释掉了,调完参数瞬间 AC

翻了一下题解发现既有用转移方程的也有没有用转移方程的,感觉很神奇,是代码实现的不同吗?

代码贴这里了

#include<bits/stdc++.h>
#define ll long long
using namespace std;
mt19937 myrand(time(0));
const double delta=0.995;
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*10+(ch-'0');
		ch=getchar();
	}
	return x*w;
}
inline int randint(int l,int r){
	return myrand()%(r-l+1)+l;
}
double n,w,h;
struct node{
	double x,y;
}a[1005];
struct NODE{
	double x,y,res;
}tmp,ans;
double check(){
	double ret=1e18;
	for(int i=1;i<=n;i++){
		ret=min(ret,sqrt((tmp.x-a[i].x)*(tmp.x-a[i].x)+(tmp.y-a[i].y)*(tmp.y-a[i].y)));
	}
	return ret;
}
void SA(){
	double T=2e3;
	while(T>=1e-16){
		while((double)clock()/CLOCKS_PER_SEC>0.96)break;
		tmp.x=(ans.x+(randint(0,w)*2.0-w)*T)*1.0;
		tmp.y=(ans.y+(randint(0,h)*2.0-h)*T)*1.0;
		if(tmp.x>w||tmp.y>h||tmp.x<0.0||tmp.y<0.0){T*=delta;continue;}
		double __tmp=check();
		double Delta=__tmp-ans.res;
		if(Delta>0){
			ans=tmp;
			ans.res=__tmp;
		}/*else if(exp(Delta/T)*RAND_MAX>randint(0,RAND_MAX)){
			ans.x=tmp.x;
			ans.y=tmp.y;
		}*/
		T*=delta;
	}
	/*for(int i=1;i<=200;i++){
		tmp.x=(ans.x+(randint(0,w)*2.0-w)*T)*1.0;
		tmp.y=(ans.y+(randint(0,h)*2.0-h)*T)*1.0;
		if(tmp.x>w||tmp.y>h||tmp.x<0.0||tmp.y<0.0)continue;
		double __tmp=check();
		double Delta=__tmp-ans.res;
		if(Delta>0){
			ans=tmp;
			ans.res=__tmp;
		}else if(exp(Delta/T)*RAND_MAX>randint(0,RAND_MAX)){
			ans.x=tmp.x;
			ans.y=tmp.y;
		}
	}*/
}
int main(){
	srand(time(0));
	w=read();h=read();n=read();
	for(int i=1;i<=n;i++){
		a[i].x=read()*1.0;
		a[i].y=read()*1.0;
	}
	tmp.x=ans.x=w/2.0,tmp.y=ans.y=h/2.0,ans.res=check();
	while((double)clock()/CLOCKS_PER_SEC<0.9)SA();
	printf("%.10f",ans.res);
	return 0;
}
2024/10/17 17:34
加载中...