POJ 1379-Run Away解题报告

模拟退火,第一次做模拟退火,搞了好几天才明白原理是怎么回事,启发式算法,运行时程序不稳定,会有一定的概率性,这些启发式算法有很多共同的特点,百度百科里有对启发式算法的简单介绍,数学中国网有很多模拟退火和其他启发式算法的很多资料,主要是数学建模方面的,但是知识都是互通的,学一学也很好,http://baike.baidu.com/view/476038.htm

其实看程序就比较好理解启发式算法的思想了,但是我找了很多解题报告,发现都没有出现概率性选择并不是最优解的解决办法,有的利用了同时产生好几个点,利用并发性,这也不能算是概率性选择,还是搞不太明白怎么办。但是就这道题说还是比较简单的,确定步长,减小速度为0.9,因为精度比较低,所以就比较好办了。保存一个当前最优解集,利用随机性,步长和最优解集产生新的最优解集,最后得到的解有很大程度上不是最优解,但是对于这道题这个精度来说还是可以做到的。

View Code
 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cmath>
 4 #include<cstring>
 5 #include<string>
 6 #include<ctime>
 7 #include<cstdlib>
 8 #define inf 1e50
 9 using namespace std;
10 const int NUM=20;
11 const int RAD=1000;
12 struct point
13 {
14     double x,y,val;
15     point(){}
16     point(double _x,double _y)
17     {
18         x=_x;
19         y=_y;
20     }
21 };
22 point p[10001],May[NUM],e1,e2;
23 int n;
24 double X,Y;
25 double dis(point a,point b)
26 {
27     return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
28 }
29 double judge(point t)//评价函数,得到点t的评价值val
30 {
31     double len=inf;
32     for(int i=0;i<n;i++)
33     len=min(len,dis(t,p[i]));
34     return len;
35 }
36 double Rand(){return rand()%(RAD+1)/(1.0*RAD);}//随机产生0-1的浮点数
37 point Rand_point(point a,point b)//在a,b框定的四边形内随机生成点
38 {
39     double xx=a.x+(b.x-a.x)*Rand();
40     double  yy=a.y+(b.y-a.y)*Rand();
41     point tmp=point(xx,yy);
42     tmp.val=judge(tmp);
43     return tmp;
44 }
45 void solve(double D)
46 {
47     May[0]=point(0,0);
48     May[1]=point(X,Y);
49     May[2]=point(0,Y);
50     May[3]=point(X,0);
51     //4个顶点的可能行较大,所以特殊构造
52     for(int i=4;i<NUM;i++)
53     May[i]=Rand_point(May[0],May[1]);//步骤2
54     while(D>0.01)//步骤 3
55     {
56         for(int i=0;i<NUM;i++)
57         for(int j=0;j<NUM;j++)
58         {
59             point tmp=Rand_point(point(max(0.0,May[i].x-D),max(0.0,May[i].y-D)),point(min(X,May[i].x+D),min(Y,May[i].y+D)));
60             if(tmp.val>May[i].val)
61             {
62                 May[i]=tmp;
63             }
64         }
65         D*=0.9;
66     }
67     point ans;
68     ans.val=0;
69     for(int i=0;i<NUM;i++)
70     if(May[i].val>ans.val)
71     ans=May[i];
72     printf("The safest point is (%.1f, %.1f).\n",ans.x,ans.y);
73 }
74 int main()
75 {
76     srand(time(0));
77     e2=point(0,0);
78     int Case;
79     int i;
80     scanf("%d",&Case);
81     while(Case--)
82     {
83         scanf("%lf%lf%d",&X,&Y,&n);
84         for(i=0;i<n;i++)
85         {
86             scanf("%lf%lf",&p[i].x,&p[i].y);
87         }
88         solve(max(Y,X));
89     }
90     return 0;
91 }

 

转载于:https://www.cnblogs.com/caozhenhai/archive/2012/10/06/2713280.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值