HDU 5017 Ellipsoid 模拟退火

说是找椭球面上的 到原点距离最近的点。

感觉像是有个单调性,然后,点的范围是正负100以内。

第一次学习模拟退火,觉得就是个搜索,在现在确定的一个方向中去搜索。当然,方向越多搜索越精确,但是时间会变慢,这种概率算法还是不要轻易写的为好......

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cstdlib>
#include <iostream>
#include <vector>
#include <cmath>
#include <queue>
#include <map>
#include <string>
#include <stack>

using namespace std;
double a,b,c,d,e,f,speed=0.99,nx,ny,nz;
double eps=1e-8;
double dd[8][2]={{1,0},{-1,0},{0,1},{0,-1},{1,-1},{1,1},{-1,1},{-1,-1}};
double dis(double a,double b,double c)
{
    return sqrt(a*a+b*b+c*c);
}
double getnz(double x,double y)
{
    double A=c;
    double B=(e*x+d*y);
    double C=a*x*x+b*y*y+f*x*y-1;
    double det=B*B-4*A*C;
    if (det<0) return 0x7f7f7f7f;
    double p=(sqrt(det)-B)/2.0/A,q=(-sqrt(det)-B)/2.0/A;
    if (p*p>q*q) return q;
    else return p;
}
void solve()
{
    double step=1;
    nx=0;
    ny=0;
    nz=getnz(nx,ny);
    while (step>eps)
    {
        for (int i=0;i<8;i++)
        {
            double tx=nx+dd[i][0]*step;
            double ty=ny+dd[i][1]*step;
            double tz=getnz(tx,ty);
            if (tz==0x7f7f7f7f) continue;
            if (dis(tx,ty,tz)<dis(nx,ny,nz))
            {
                nx=tx,ny=ty,nz=tz;
            }
        }
        step*=speed;
    }
    printf ("%.10f\n",dis(nx,ny,nz));
}
int main()
{
    while (scanf ("%lf%lf%lf%lf%lf%lf",&a,&b,&c,&d,&e,&f)!=EOF)
    {
        solve();
    }
    return 0;
}

 

posted on 2016-07-25 12:11  very_czy  阅读(194)  评论(0编辑  收藏  举报

导航