模拟退火。。。。看的别人的思想。。。貌似就是分成N块 在每快内收敛。。。
AC代码如下:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
#define MAX 0x3f3f3f3f
#define NUM 20//搜索块的大小
#define EPS 1e-2//精度
typedef struct{
double x, y, dis;
}Point;
const double PI = acos(-1.0);
Point temp[55], p[1000];
int M;
double X, Y;
double calc_dis( Point a, Point b ){
return sqrt( ( a.x - b.x ) * ( a.x - b.x ) + ( a.y - b.y ) * ( a.y - b.y ) );
}
void search(){
for( int i = 0; i < NUM; i++ ){
temp[i].x = ( rand() % 1000 + 1.0 ) / 1000.0 * X;
temp[i].y = ( rand() % 1000 + 1.0 ) / 1000.0 * Y;
double dis = MAX;
for( int j = 0; j < M; j++ ){
dis = min( dis, calc_dis( temp[i], p[j] ) );
}
temp[i].dis = dis;
}
double upbond = 1.0 * max( X, Y ) / sqrt( NUM * 1.0 );
while( upbond > EPS ){
for( int i = 0; i < NUM; i++ ){
for( int j = 0; j < NUM; j++ ){
double angle = 1.0 * ( rand() % 1000 ) / 1000.0 * 2 * PI;
double tempx = temp[i].x + upbond * cos( angle );
double tempy = temp[i].y + upbond * sin( angle );
if( tempx < 0 || tempx > X || tempy < 0 || tempy > Y ){
continue;
}
double dis = MAX;
Point tempp;
tempp.x = tempx;
tempp.y = tempy;
for( int k = 0; k < M; k++ ){
dis = min( dis, calc_dis( tempp, p[k] ) );
}
if( dis > temp[i].dis ){
temp[i].dis = dis;
temp[i].x = tempx;
temp[i].y = tempy;
}
}
}
upbond *= 0.5;
}
int ans = 0;
for( int i = 0; i < NUM; i++ ){
if( temp[i].dis > temp[ans].dis ){
ans = i;
}
}
printf( "The safest point is (%0.1lf, %0.1lf).\n", temp[ans].x, temp[ans].y );
}
int main(){
int T;
cin >> T;
while( T-- ){
cin >> X >> Y >> M;
for( int i = 0; i < M; i++ ){
cin >> p[i].x >> p[i].y;
}
search();
}
return 0;
}