模拟退火,AC42+WA8 如何解决?
#include<bits/stdc++.h>
#define int long long
#define endl '\n'
#define N 106
using namespace std;
const double eps=1e-9;
int n;
double minn=1e15;
struct Point{double x,y;}ans;
struct Seg{Point l,r;}a[N];
struct Line{double k,b;};
Point cross(Line x,Line y)
{
double posx=(y.b-x.b)/(x.k-y.k);
double posy=x.k*posx+x.b;
return {posx,posy};
}
double getdis(Point x,Point y)
{
double ret=(x.x-y.x)*(x.x-y.x)+(x.y-y.y)*(x.y-y.y);
return pow(ret,0.5);
}
Point foot(Point x,Line y)
{
Line newL={-1.0/y.k,x.y+1.0/y.k*x.x};
return cross(newL,y);
}
double getdis(Point x,Seg y)
{
double ans0=min(getdis(x,y.l),getdis(x,y.r));
if(y.l.x==y.r.x)
{
double maxn=max(y.l.y,y.r.y),minn=min(y.l.y,y.r.y);
if(x.y>=minn&&x.y<=maxn)ans0=min(ans0,fabs(x.x-y.l.x));
return ans0;
}
double K=(y.r.y-y.l.y)/(y.r.x-y.l.x);
double B=y.l.y-K*y.l.x;
Line newL={K,B};
Point ft=foot(x,newL);
double maxn=max(y.l.x,y.r.x),minn=min(y.l.x,y.r.x);
if(minn<=ft.x&&ft.x<=maxn)ans0=min(ans0,getdis(x,ft));
return ans0;
}
double getans(Point x)
{
double ans=-1e15;
for(int i=1;i<=n;i++)ans=max(ans,getdis(x,a[i]));
return ans;
}
void SA()
{
double T=1e4;srand(time(0));
while(T>1e-15)
{
Point tmp={ans.x+(rand()*2-RAND_MAX)*T,ans.y+(rand()*2-RAND_MAX)*T};
double delta=getans(tmp)-minn;
if(delta<0)ans=tmp,minn=getans(tmp);
else if(exp(-delta/T)*RAND_MAX>rand())ans=tmp;
T*=0.996;
}
}
main()
{
scanf("%lld",&n);
for(int i=1;i<=n;i++)
{
scanf("%lf%lf%lf%lf",&a[i].l.x,&a[i].l.y,&a[i].r.x,&a[i].r.y);
ans.x+=a[i].l.x/2.0/n+a[i].r.x/2.0/n;
ans.y+=a[i].l.y/2.0/n+a[i].r.y/2.0/n;
}
minn=getans(ans);
for(int i=1;i<=10;i++)SA();
printf("%.20lf",minn);
return 0;
}