模拟退火绝对是从OI--ACM以来接触过的所有算法里面最黑科技的orz
题意:地上有一堆hole,要找一个点,使得(距离该点最远的hole的距离)最小。
sol:本来想套昨天的模拟退火模板,初值(0,0),向8个方向扩散。
然而这题并没有这么naive。
模板2.0 get:
1 #define eps 1e-3 2 #define pi acos(-1.0) 3 #define POI 15 //独立跑POI次,找其中最小的 tp[1..POI]是随机的初值 4 #define RUN 40 //迭代次数,本题中即点(tx,ty)向RUN个方向发散 5 6 7 void sa() 8 { 9 for(int i=1;i<=POI;i++) 10 { 11 tp[i].x=(rand()%1000+1)/1000.0*X; 12 tp[i].y=(rand()%1000+1)/1000.0*Y; 13 sol[i]=dis(tp[i].x,tp[i].y); 14 //printf("%.1f~%.1f=%.1f ",tp[i].x,tp[i].y,sol[i]); 15 } 16 17 double step=1.0*max(X,Y)/sqrt(1.0*N); 18 while(step>eps) 19 { 20 for(int i=1;i<=POI;i++) 21 { 22 double kx=tp[i].x,ky=tp[i].y; 23 double tx=kx,ty=ky; 24 for(int j=0;j<RUN;j++) 25 { 26 double angle=(rand()%1000+1)/1000.0*10*pi; 27 kx=tx+cos(angle)*step; 28 ky=ty+sin(angle)*step; 29 if((kx>X)||(ky>Y)||(kx<0)||(ky<0)) continue; 30 double tmp=dis(kx,ky); 31 if(tmp<sol[i]) 32 { 33 tp[i].x=kx; tp[i].y=ky; 34 sol[i]=tmp; 35 } 36 } 37 } 38 step*=0.80; 39 } 40 }
AC Code:
1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<ctime> 5 using namespace std; 6 7 #define eps 1e-3 8 #define pi acos(-1.0) 9 #define POI 15 //独立跑POI次,找其中最小的 tp[1..POI]是随机的初值 10 #define RUN 40 //迭代次数,本题中即点(tx,ty)向RUN个方向发散 11 int X,Y,N; 12 double ans; 13 int ansi; 14 struct 15 { 16 double x,y; 17 }tp[1010],hol[1010]; 18 double sol[1010]; 19 20 double dist(double x1,double y1,double x2,double y2) 21 { 22 return(sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2))); 23 } 24 25 double dis(double x,double y) 26 { 27 double tmp=0.000; 28 for(int i=1;i<=N;i++) 29 { 30 double tx=hol[i].x,ty=hol[i].y; 31 tmp=max(tmp,dist(tx,ty,x,y)); 32 } 33 return tmp; 34 } 35 36 void sa() 37 { 38 for(int i=1;i<=POI;i++) 39 { 40 tp[i].x=(rand()%1000+1)/1000.0*X; 41 tp[i].y=(rand()%1000+1)/1000.0*Y; 42 sol[i]=dis(tp[i].x,tp[i].y); 43 //printf("%.1f~%.1f=%.1f ",tp[i].x,tp[i].y,sol[i]); 44 } 45 46 double step=1.0*max(X,Y)/sqrt(1.0*N); 47 while(step>eps) 48 { 49 for(int i=1;i<=POI;i++) 50 { 51 double kx=tp[i].x,ky=tp[i].y; 52 double tx=kx,ty=ky; 53 for(int j=0;j<RUN;j++) 54 { 55 double angle=(rand()%1000+1)/1000.0*10*pi; 56 kx=tx+cos(angle)*step; 57 ky=ty+sin(angle)*step; 58 if((kx>X)||(ky>Y)||(kx<0)||(ky<0)) continue; 59 double tmp=dis(kx,ky); 60 if(tmp<sol[i]) 61 { 62 tp[i].x=kx; tp[i].y=ky; 63 sol[i]=tmp; 64 } 65 } 66 } 67 step*=0.80; 68 } 69 } 70 71 72 int main() 73 { 74 srand(time(NULL)); 75 while(cin>>X>>Y>>N) 76 { 77 for(int i=1;i<=N;i++) 78 cin>>hol[i].x>>hol[i].y; 79 80 sa(); 81 82 ans=(X*X+Y*Y)*100.0; 83 for(int i=1;i<=POI;i++) 84 { 85 //printf("AA: %.1f~%.1f=%.1f ",tp[i].x,tp[i].y,sol[i]); 86 if(sol[i]<ans) 87 { 88 ans=sol[i]; 89 ansi=i; 90 } 91 } 92 printf("(%.1f,%.1f). ",tp[ansi].x,tp[ansi].y); 93 printf("%.1lf ",ans); 94 } 95 return 0; 96 }
ref:
http://blog.csdn.net/acm_cxlove/article/details/7954321
http://blog.csdn.net/zxy_snow/article/details/6682926
http://www.kuangbin.net/archives/hdu3932#more-435