POJ 2420 模擬退火求費馬點
題意求一個多邊形的費馬點,即到所有頂點距離和最小的那一點。
以前覺得模擬退火好高端的樣子,實際就是把點往四個方向移動固定步長,知道不能移動後縮小步長繼續移動,也就是隨機求一個接近最優並且滿足精度的解。
#include <iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> using namespace std; typedef double diy; struct point { diy x,y; point() {} point(diy _x,diy _y):x(_x),y(_y) {} }; double step[4][2]= {0,1,0,-1,-1,0,1,0}; 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 disall(point a,point *g,int n) { int i=0; double sum=0; while(n--) sum+=dis(a,g[i++]); return sum; } double SAnnealing(point *g,int n) { point t=g[0]; int flag; double ret=disall(t,g,n),st; for(st=100; st>1e-1; st*=0.98) { flag=1; while(flag) { flag=0; for(int i=0; i<4; i++) { point now(t.x+step[i][0]*st,t.y+step[i][1]*st); double nowdis=disall(now,g,n); if(nowdis<ret) t=now,flag=1,ret=nowdis; } } } return ret; } int main() { int n; point data[105]; while(~scanf("%d",&n)) { for(int i=0; i<n; i++) scanf("%lf%lf",&data[i].x,&data[i].y); printf("%.0f\n",SAnnealing(data,n)); } return 0; }
最後更新:2017-04-03 18:52:08