hdu 5017 模拟退火
题意:给出椭球面的立体解析式,要求椭球面上距离原点最近的点的距离
sol:这题要想推公式就😶😶😶。。。【可以试试二元函数求极值
一种比较普遍的解法是模拟退火
模拟退火的解释可以参考这儿:http://www.cnblogs.com/heaad/archive/2010/12/20/1911614.html
模拟退火模板get:
1 double sa() //Simulated_Annealing 2 { 3 double x = 0,y = 0,z = sqrt(1.0/C); //当前最优解 4 double step = 1.0, rate = 0.99; //step:系统温度 rate:控制降温的速度 5 while(step > eps) 6 { 7 for(int k=0;k<8;k++) //(x,y)可以向8个方向扩散,z直接用解析式算出,这样就保证了(x,y,z)一定在椭球面上 8 { 9 double kx = x + step*dx[k]; 10 double ky = y + step*dy[k]; 11 double kz = calc(kx,ky); 12 if(kz >= Mod) continue; //不符合要求的筛掉 13 if(dis(kx,ky,kz) < dis(x,y,z)) 14 { 15 x = kx,y = ky,z = kz; 16 } 17 } 18 step *= rate; 19 } 20 return dis(x,y,z); 21 }
AC Code:
1 #include<iostream> 2 #include<cmath> 3 using namespace std; 4 int dx[10]={-1, 0, 1,1,1,0,-1,-1}; 5 int dy[10]={-1,-1,-1,0,1,1, 1, 0}; 6 double A,B,C,D,E,F; 7 #define Mod 1000000007 8 #define eps 1e-8 9 10 double dis(double x,double y,double z) 11 { 12 return(sqrt(x*x+y*y+z*z)); 13 } 14 15 double calc(double x,double y) 16 { 17 double tb=(D*y+E*x)*(D*y+E*x)-4*C*(A*x*x+B*y*y+F*x*y-1); 18 double ta=-D*y-E*x; 19 tb=sqrt(tb); 20 double tx=(ta+tb)/(2*C),ty=(ta-tb)/(2*C); 21 if(dis(x,y,tx)<dis(x,y,ty)) return tx; else return ty; 22 } 23 24 double sa() //Simulated_Annealing 25 { 26 double x = 0,y = 0,z = sqrt(1.0/C); //当前最优解 27 double step = 1.0, rate = 0.99; //step:系统温度 rate:控制降温的速度 28 while(step > eps) 29 { 30 for(int k=0;k<8;k++) //(x,y)可以向8个方向扩散,z直接用解析式算出,这样就保证了(x,y,z)一定在椭球面上 31 { 32 double kx = x + step*dx[k]; 33 double ky = y + step*dy[k]; 34 double kz = calc(kx,ky); 35 if(kz >= Mod) continue; //不符合要求的筛掉 36 if(dis(kx,ky,kz) < dis(x,y,z)) 37 { 38 x = kx,y = ky,z = kz; 39 } 40 } 41 step *= rate; 42 } 43 return dis(x,y,z); 44 } 45 46 47 int main() 48 { 49 while(cin>>A>>B>>C>>D>>E>>F) 50 { 51 printf("%.7f\n",sa()); 52 } 53 return 0; 54 }
Reference:
http://www.cnblogs.com/whatbeg/p/3975624.html
http://blog.csdn.net/zz_1215/article/details/40923313(zz大神的奇怪做法,orz)
posted on 2015-05-28 18:01 Pentium.Labs 阅读(174) 评论(0) 编辑 收藏 举报