1 0.04 0.01 0 0 0
1.0000000
第一次了解模拟退火。
求z时已知x,y转化为关于z的二次方程,用韦达定理求z。
关于退火速度,測了一下,r=0.99时是281ms,r=0.98时是140ms,r=0.97时是93ms,r=0.96时就wa了。
代码:、
//97ms #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> using namespace std; const int dx[8]={0,0,1,-1,1,-1,1,-1}; const int dy[8]={1,-1,0,0,-1,1,1,-1}; const double r=0.97; const double eps=1e-8; double a,b,c,d,e,f; double dis(double x,double y,double z) { return sqrt(x*x+y*y+z*z); } double getz(double x,double y)//求z { double A=c; double B=d*y+e*x; double C=f*x*y+a*x*x+b*y*y-1; double delta=B*B-4*A*C; if(delta<0) { return 1e30; } else { double z1=(-B+sqrt(delta))/A/2; double z2=(-B-sqrt(delta))/A/2; return z1*z1<z2*z2?z1:z2; } } double anneal()//退火 { double step=1; double x=0,y=0,z; while(step>eps) { z=getz(x,y); for(int i=0;i<8;i++) { double xi=x+dx[i]*step; double yi=y+dy[i]*step; double zi=getz(xi,yi); if(zi>1e20) continue; if(dis(xi,yi,zi)<dis(x,y,z)) { x=xi; y=yi; z=zi; } } step=step*r; } return dis(x,y,z); } int main() { while(~scanf("%lf%lf%lf%lf%lf%lf",&a,&b,&c,&d,&e,&f)) { printf("%.8f\n",anneal()); } return 0; }