hdu3932 模拟退火

模拟退火绝对是从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 }
View Code

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

原文地址:https://www.cnblogs.com/pdev/p/4539270.html