題目大意:給一個矩陣的長寬,再給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; }