模拟退火 lgP5544题解

题目大意

题意这么明显就不说了qwq

首先最值,而且也想不到啥解法,果断 \(\rm SA\)。

然后是初始位置。初始位置就是 \(((\sum_{i=1}^m x)/m,(\sum_{i=1}^m y)/m)\)。

然后多跑几遍 \(\rm SA\) 就行了qwq。本人跑了55遍,提交过100多遍,虽然说Ynoi比这个还要狠。

code:

#pragma GCC optimize("-fipa-sra")
#pragma GCC optimize("inline")
#pragma GCC optimize("-fgcse")
#pragma GCC optimize("Ofast")
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#include<iostream>
#include<cstdlib>
#include<cmath>
#include<ctime>
typedef double db;
const db delta=0.99;
db x,y;
struct Node{
	int x,y,r;
}a[15],w[1005];
int n,m,k,r,ans;
inline db p(const db x){
	return x*x;
}
inline db DIS(db x,db y,db a,db b){
	return sqrt(p(x-a)+p(y-b));
}
int calc_energy(const register db x,const register db y){
	register int i,ans=0;
	register db Dis=r;
	for(i=1;i<=n;++i){
		db dis=DIS(a[i].x,a[i].y,x,y)-a[i].r;
		if(dis<0)return 0;
		if(Dis>dis)Dis=dis;
	}
	for(i=1;i<=m;++i)if(DIS(w[i].x,w[i].y,x,y)<=Dis)++ans;
	return ans;
}
void simulate_anneal(){
	db ax=x,ay=y;
	for(register db t=3000;t>1e-16;t*=delta){
		db X=x+((rand()<<1)-RAND_MAX)*t,Y=y+((rand()<<1)-RAND_MAX)*t;
		db now=calc_energy(X,Y);db Delta=ans-now;
		if(Delta<0)x=ax=X,y=ay=Y,ans=now;
		if(exp(-Delta/t)<rand())ax=X,ay=Y;
	}
}
signed main(void){
	srand(time(NULL));
	std::ios::sync_with_stdio(false);
	std::cin.tie(0);std::cout.tie(0);
	int i;
	std::cin>>n>>m>>r;
	for(i=1;i<=n;++i){
		std::cin>>a[i].x>>a[i].y>>a[i].r;
	}
	for(i=1;i<=m;++i){
		std::cin>>w[i].x>>w[i].y;
		x+=w[i].x;y+=w[i].y;
	}
	x/=m;y/=m;
	for(i=1;i<=55;++i)simulate_anneal();
	std::cout<<ans;
}
上一篇:Centos安装Sublime text


下一篇:Rust 使用 dotenv 来设置环境变量