爬山算法与模拟退火算法

POJ2420

给n个点,找出一个点,使这个点到其他所有点的距离之和最小,也就是求费马点

爬山算法就是一只兔子看到一座山峰,然后跳来跳去最后跳上山顶

模拟退火就是一只喝醉的兔子,一开始乱跳,过一会酒醒了,然后再跳上山顶

爬山算法也是一个用来求解最优化问题的算法,每次都向着当前上升最快的方向往上爬

但是初始化不同可能会得到不同的局部最优值

模拟退火算法就可能跳出这种局部最优解的限制

模拟退火算法也是贪心算法,但是在其过程中引入了随机因素,以一定的概率接受一个比当前解要差的解

并且这个概率随着时间的推移而逐渐降低

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cmath>
 4 using namespace std;
 5 int n;
 6 double xx,yy,ans,t;
 7 struct point{double x,y;}p[105];
 8 double sqr(double x){return x*x;}
 9 double dis(double x,double y,point p)
10 {return sqrt(sqr(x-p.x)+sqr(y-p.y));}
11 double getsum(double x,double y)
12 {
13     double tmp=0;
14     for(int i=1;i<=n;i++)
15         tmp+=dis(x,y,p[i]);
16     return tmp;
17 }
18 int main()
19 {
20     while(scanf("%d",&n)!=EOF)
21     {
22         xx=yy=0;ans=1e20;t=10000;
23         for(int i=1;i<=n;i++)
24         {
25             scanf("%lf%lf",&p[i].x,&p[i].y);
26             xx+=p[i].x;yy+=p[i].y;
27         }
28         xx/=n;yy/=n;
29         ans=getsum(xx,yy);
30         double tmp,x,y;
31         while(t>0.02)
32         {
33             x=y=0;
34             for(int i=1;i<=n;i++)
35             {
36                 x+=(p[i].x-xx)/dis(xx,yy,p[i]);
37                 y+=(p[i].y-yy)/dis(xx,yy,p[i]);
38             }
39             tmp=getsum(xx+x*t,yy+y*t);
40             if(tmp<ans){ans=tmp;xx+=x*t,yy+=y*t;}
41             t*=0.9;
42         }
43         printf("%.0lf\n",ans);
44     }
45     return 0;
46 }

以上是爬山算法的,然后是模拟退火算法

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstdlib>
 4 #include<cmath>
 5 #include<ctime>
 6 using namespace std;
 7 int n;
 8 double xx,yy,ans,t;
 9 struct point{double x,y;}p[105];
10 double sqr(double x){return x*x;}
11 double dis(double x,double y,point p)
12 {return sqrt(sqr(x-p.x)+sqr(y-p.y));}
13 double getsum(double x,double y)
14 {
15     double tmp=0;
16     for(int i=1;i<=n;i++)
17         tmp+=dis(x,y,p[i]);
18     return tmp;
19 }
20 int main()
21 {
22     srand(time(0));
23     while(scanf("%d",&n)!=EOF)
24     {
25         xx=yy=0;ans=1e20;t=100000;
26         for(int i=1;i<=n;i++)
27         {
28             scanf("%lf%lf",&p[i].x,&p[i].y);
29             xx+=p[i].x;yy+=p[i].y;
30         }
31         xx/=n;yy/=n;
32         ans=getsum(xx,yy);
33         double tmp,x,y;
34         while(t>0.02)
35         {
36             x=y=0;
37             for(int i=1;i<=n;i++)
38             {
39                 x+=(p[i].x-xx)/dis(xx,yy,p[i]);
40                 y+=(p[i].y-yy)/dis(xx,yy,p[i]);
41             }
42             tmp=getsum(xx+x*t,yy+y*t);
43             if(tmp<ans)
44             {ans=tmp;xx+=x*t,yy+=y*t;}
45             else if(log((tmp-ans)/t)<(rand()%10000)/10000.0)
46             {ans=tmp;xx+=x*t,yy+=y*t;}       
47             t*=0.9; 
48         }
49         printf("%.0lf\n",ans);
50     }
51     return 0;
52 }

猜你喜欢

转载自www.cnblogs.com/aininot260/p/9635617.html