Ellipsoid
题目链接:
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());
}