题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=5017
解题思路:
题目大意:
求(0,0,0)到椭圆表面最短距离。
解题思路:
模拟退火算法
有关于模拟退火算法请参考于:
http://zh.wikipedia.org/wiki/%E6%A8%A1%E6%8B%9F%E9%80%80%E7%81%AB
http://www.cnblogs.com/heaad/archive/2010/12/20/1911614.html
AC代码:
#include <iostream> #include <cstdio> #include <cmath> using namespace std; const double INF = 0x3f3f3f3f; const double eps = 1e-9; const double r = 0.9; //降温速度 const int dx[] = {-1,0,1,-1,1,-1,0,1},dy[] = {1,1,1,0,0,-1,-1,-1}; double a,b,c,d,e,f; double dis(double x,double y,double z){ return sqrt(x*x+y*y+z*z); } //已知x,y;求z(把x,y看做常量,z看做变量,求解普通的一元二次方程即可) double getZ(double x,double y){ double tmp = (d*y+e*x)*(d*y+e*x)-4*c*(a*x*x+b*y*y+f*x*y-1); if(tmp < 0) return 10; //返回一个大于2的值即可, double z1 = (-(d*y+e*x)+sqrt(tmp))/(2*c); double z2 = (-(d*y+e*x)-sqrt(tmp))/(2*c); if(z1*z1 <= z2*z2) return z1; else return z2; } //模拟退火算法 double solve(){ double step = 1; double x = 0,y = 0,z,nx,ny,nz; double ans = INF,sum; int flag; while(step > eps){ flag = 1; while(flag){ flag = 0; for(int i = 0; i < 8; i++){ nx = x+dx[i]*step; ny = y+dy[i]*step; nz = getZ(nx,ny); if(nz > 2) //此处应是一个大于1的值最好是2以上,因为double continue; sum = dis(nx,ny,nz); if(ans > sum){ x = nx;y = ny; ans = sum; flag = 1; } } } step *= r; } return ans; } int main(){ while(scanf("%lf%lf%lf%lf%lf%lf",&a,&b,&c,&d,&e,&f)!=EOF) printf("%.8lf\n",solve()); }