模拟:爬山算法与模拟退火算法
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 }