【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 }

 

 

posted @ 2018-08-23 21:36  noble_(noblex)  阅读(373)  评论(0编辑  收藏  举报
/* */