萌新刚学OI,求助退火
查看原帖
萌新刚学OI,求助退火
253738
听取MLE声一片楼主2022/3/16 23:11

调废了/ll,第三个点挂了,点数多点第七个T了

#include<bits/stdc++.h>
using namespace std;
inline int read(){
	int x=0,f=1;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
	return x*f;
}
const int N=1e3+10;
int n,k,flag;
double len,d[N],ans;
struct point{
	double x,y;
}a[N],b[N];
double dis(point a,point b){
	return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
double sum(point a,point b,point c){
	double x=dis(a,b),y=dis(b,c),z=dis(c,a);
	double p=(x+y+z)/2;
	return sqrt(p*(p-x)*(p-y)*(p-z));
}
double solve(double l){
	int pp=l;
	d[n]+=pp;
	int cnt=1;
	for(int i=1;i<=k;i++){
		while(l>=d[cnt]){
			l-=d[cnt];
			cnt++;
		}
		double xx=a[cnt%n+1].x-a[cnt].x,yy=a[cnt%n+1].y-a[cnt].y;
		b[i].x=a[cnt].x+xx*l/d[cnt],b[i].y=a[cnt].y+yy*l/d[cnt];
		l=len+l;
		//cout<<i<<' '<<b[i].x<<' '<<b[i].y<<endl;
	}
	//cout<<endl;
	d[n]-=pp;
	double s=0;
	for(int i=2;i<k;i++)
		s+=sum(b[1],b[i],b[i+1]);
	return s;
}
double rnd(double a,double b){
	flag+=1000;
	default_random_engine random(114514+flag); 
	uniform_real_distribution<double> p(a,b);
	return p(random);
}
void SA(){
	double x=rnd(0,len),res=solve(x);
	ans=min(ans,res);
	double t=10000,T=t,p=0.995;
    while(T>1e-10){
        double l=len*T/t;
        double xx=rnd(max(x-l,0.0),min(x+l,len));
        double s=solve(xx);
		//cout<<xx<<' '<<s<<" "<<ans<<endl;
        ans=min(ans,s);
        if(x<res||rnd(0,1)<exp((res-s)/T))
			x=xx,res=s;
        T*=p;
    }
    //cout<<ans<<endl;
}
int main()
{
	n=read(),k=read();
	for(int i=1;i<=n;i++){
		cin>>a[i].x>>a[i].y;
		if(i!=1){
			d[i-1]=dis(a[i],a[i-1]);
			len+=d[i-1];
		}
	}
	d[n]=dis(a[1],a[n]);
	len+=d[n];
	len=len/k;
	ans=1e18;
	for(int i=1;i<=50;i++){
		flag+=i*10000;
		SA();
	}
	printf("%.10lf",ans);
	return 0;
}

2022/3/16 23:11
加载中...