题目大意:给一个矩阵的长宽,再给n个点,求矩阵区域内某个点到各个点的最小距离的最大值,输出所求点的坐标dom
这道题我仍是写了随机化乱搞,不过因为比较懒因而就没有写模拟退火,不过也是能够AC的spa
咱们先初始随机一个坐标并算出它的答案,而后每一次择状况随机一个步长(这个要随着时间的推移慢慢变小),而后随机角度获得新的点坐标。code
同时咱们计算出新的点的答案而后和当前的答案比对一下,若是更优就选择便可。string
注意一下:这不是模拟退火,真正的模拟退火仍是有一个几率接受较差解的过程的,并且是根据老天爷的规律得出的,所以比较科学。io
仍是一句老话,脸黑就多rand几回,通常来讲没什么大问题就过了class
CODEim
#include<cstdio> #include<cctype> #include<cstring> #include<cstdlib> #include<ctime> #include<cmath> using namespace std; typedef double DB; const DB EPS=1e-3,dlt=0.85,pi=acos(-1.0); const int N=1005,EXP=10000; struct Point { DB x,y; }a[N],ans; int t,n; DB X,Y,mx; inline DB random(DB l,DB r) { return (DB)(rand()%EXP)/EXP*(r-l)+l; } inline DB min(DB a,DB b) { return a<b?a:b; } inline DB dis(Point A,Point B) { return (DB)sqrt((A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y)); } inline DB calc(Point s) { DB d=dis(s,a[1]); for (register int i=2;i<=n;++i) d=min(d,dis(s,a[i])); return d; } inline DB Simulate_Anneal(Point &s) { DB d=calc(s),step=X>Y?X:Y; while (step>EPS) { for (register int i=1;i<=50;++i) { DB angle=random(0,2*pi),x=s.x+cos(angle)*step,y=s.y+sin(angle)*step; if (x>=0&&x<=X&&y>=0&&y<=Y&&calc((Point){x,y})>d) s=(Point){x,y},d=calc(s); } step*=dlt; } return d; } int main() { register int i; srand(time(0)); scanf("%d",&t); while (t--) { scanf("%lf%lf%d",&X,&Y,&n); mx=0; for (i=1;i<=n;++i) scanf("%lf%lf",&a[i].x,&a[i].y); for (i=1;i<=50;++i) { Point P=(Point){random(0,X),random(0,Y)}; DB d=Simulate_Anneal(P); if (d>mx) mx=d,ans=P; } printf("The safest point is (%.1lf, %.1lf).\n",ans.x,ans.y); } return 0; }