模拟退火算法,很久之前就写过一篇文章了。双倍经验题(POJ 2420)
题意:
在一个矩形区域内,求一个点的距离到所有点的距离最短的那个,最大。
这个题意,很像二分定义,但是毫无思路,也不能暴力枚举,那就模拟退火。
#include <stdio.h> #include <math.h> #include <algorithm> using namespace std; const int maxn = 1005; int X,Y,M; int Kase; struct Node { double x,y; }nodes[maxn]; int dx[4] = {0,0,-1,1}; int dy[4] = {-1,1,0,0}; double dist(Node a,Node b) { return sqrt( (a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y)); } double calc(Node p) { double ret = 0x3f3f3f3f; for(int i = 0; i < M; i++) ret = min(ret,dist(p,nodes[i])); return ret; } int main() { //freopen("in.txt","r",stdin); scanf("%d",&Kase); while(Kase--) { scanf("%d%d%d",&X,&Y,&M); for(int i = 0; i < M; i++) scanf("%lf%lf",&nodes[i].x,&nodes[i].y); Node s; s.x = X/2; s.y = Y/2; double t = max(X,Y); double ansx = X/2; double ansy = Y/2; double ans = calc(s); Node tmp; tmp.x = 0; tmp.y = 0; double anstmp = calc(tmp); if(anstmp>ans) { ans = anstmp; ansx = 0; ansy = 0; } tmp.x = 0; tmp.y = Y; anstmp = calc(tmp); if(anstmp>ans) { ans = anstmp; ansx = 0; ansy = Y; } tmp.x = X; tmp.y = 0; anstmp = calc(tmp); if(anstmp>ans) { ans = anstmp; ansx = X; ansy = 0; } tmp.x = X; tmp.y = Y; anstmp = calc(tmp); if(anstmp>ans) { ans = anstmp; ansx = X; ansy = Y; } while(t>1e-8) { bool flag = true; while(flag) { flag = false; for(int i = 0; i < 4; i++) { Node v; v.x = s.x + dx[i]*t; v.y = s.y + dy[i]*t; if(v.x>X||v.y>Y||v.x<0||v.y<0) continue; double tp = calc(v); if(tp>ans) { ans = tp; flag = true; ansx = v.x; ansy = v.y; s = v; } } } t = t*0.98; } printf("The safest point is (%.1f, %.1f).\n",ansx,ansy); } return 0; }