【POJ】2420 A Star not a Tree?(模拟退火)
题目
传送门:QWQ
分析
军训完状态不好QwQ,做不动难题,于是就学了下模拟退火。
之前一直以为是个非常nb的东西,主要原因可能是差不多省选前我试着学一下但是根本看不懂?
骗分利器,但据说由于调参困难,很多情况比不上多点爬山?
总体来说模拟退火的精髓就是:
可以看到T越大,转移的概率越高。 exp是在cmath里面有的,直接用就ok。
本题就是找出n个点的费马点,即找出一个点到这n个点的距离和最小。
代码
1 // #include <bits/stdc++.h> 2 // POJ 2420 3 #include <cstdio> 4 #include <cmath> 5 #include <cstdlib> 6 #include <ctime> 7 using namespace std; 8 const int maxn=2000; 9 const double pace=0.95; 10 struct Point { double x,y; }; 11 12 int n; 13 Point p[maxn]; 14 15 double sqr(double x){ return x*x; } 16 double dis(double x,double y,Point a){ return sqrt(sqr(x-a.x)+sqr(y-a.y)); } 17 double getnum(double x,double y){ 18 double ans=0; 19 for(int i=1;i<=n;i++) ans+=dis(x,y,p[i]); 20 return ans; 21 } 22 int main(){ 23 // srand(time(NULL)); 24 srand(0); 25 Point ans; 26 scanf("%d",&n); 27 for(int i=1;i<=n;i++) { 28 scanf("%lf%lf",&p[i].x,&p[i].y); 29 ans.x+=p[i].x; ans.y+=p[i].y; 30 } 31 ans.x/=n; ans.y/=n; 32 double t=1e5, end=0.02, pre=getnum(ans.x,ans.y); 33 while(t>end){ 34 35 double xx=0, yy=0; 36 t*=pace; 37 for(int i=1;i<=n;i++){ 38 xx+=(p[i].x-ans.x)/dis(ans.x,ans.y,p[i]); 39 yy+=(p[i].y-ans.y)/dis(ans.x,ans.y,p[i]); 40 } 41 double tmp=getnum(ans.x+xx*t,ans.y+yy*t); 42 if(tmp<pre){ 43 pre=tmp; ans.x+=xx*t; ans.y+=yy*t; 44 } 45 else if(exp((pre-tmp)/t)>(rand()%10000)/10000.0){ 46 ans.x+=xx*t; ans.y+=yy*t; 47 } 48 t*=pace; 49 } 50 printf("%.0f",pre); 51 return 0; 52 }