Groundhog Build Home HDU - 3932 【模拟退火】
题意:模拟退火就好,详细的代码注释在第一篇模拟退火里
#include<cstdio>
#include<vector>
#include<cmath>
#include<math.h>
#include<time.h>
#include<string>
#include<string.h>
#include<iostream>
#include<algorithm>
#include<map>
#define PI acos(-1.0)
#define pb push_back
#define F first
#define S second
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int N=1005;
const int MOD=1e9+7;
const double eps=1e-10;
int sign(double x) { //三态函数,减少精度问题
return abs(x) < eps ? 0 : x < 0 ? -1 : 1;
}
struct Point{
double x,y;
Point(double x=0.0,double y=0.0):x(x),y(y){}
Point operator +(const Point &rhs)const{
return Point(x+rhs.x,y+rhs.y);
}
Point operator -(const Point &rhs)const{
return Point(x-rhs.x,y-rhs.y);
}
};
Point p[N];
double X,Y;
int 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 cul(Point c){
double mx=0;
for(int i=0;i<n;i++) mx=max(mx,dis(c,p[i]));
return mx;
}
double myrand(){
return rand()%10000/10000.0;
}
void SA(Point &c,double &r){
c=Point(X/2,Y/2);
double T=sqrt(X*X+Y*Y)/2;
double E=cul(c);
while(T>eps){
Point next;
double mn=1e20;
for(int i=0;i<50;++i){
double ang=2*PI*myrand();
double x=c.x+cos(ang)*T;
double y=c.y+sin(ang)*T;
if(sign(x)<0) x=0;
if(sign(x-X)>0) x=X;
if(sign(y)<0) y=0;
if(sign(y-Y)>0) y=Y;
Point t(x,y);
double tE=cul(t);
if(tE<mn){
mn=tE;
next=t;
}
}
if(sign(mn-E)<0 || exp(mn-E)/T<myrand()){
E=mn;
c=next;
}
T*=0.8;
}
r=E;
}
void mian(){
for(int i=0;i<n;i++){
double x,y;
scanf("%lf%lf",&x,&y);
p[i]=Point(x,y);
}
Point c;
double r;
SA(c,r);
printf("(%.1f,%.1f).\n",c.x,c.y);
printf("%.1f\n",r);
}
int main(void){
srand(time(0));
while(scanf("%lf%lf%d",&X,&Y,&n)==3){
mian();
}
return 0;
}