HDU 5017 Ellipsoid 模拟退火第一题

为了补这题,特意学了下模拟退火算法,感觉算法本身不是很难,就是可能降温系数,步长等参数不好设置。

具体学习可以参见: http://www.cnblogs.com/heaad/archive/2010/12/20/1911614.html  我认为讲的很不错,通俗易懂。

这题设置一个step为1,降温系数为0.99,因为系数越大,得到最优解的概率越大,虽然可能会慢一点。因为是三维的,所以往八个方向扩展找邻域解,然后遇到比他优的解一定接受。

代码:(参照网上代码)

#include <iostream>

#include <cstdio>

#include <cstdlib>

#include <cmath>

#define Mod 1000000007

#define eps 1e-8

using namespace std;



int dx[8] = {0,0,1,-1,1,-1,1,-1};

int dy[8] = {1,-1,0,0,1,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);

}



double calc(double x,double y)

{

    double A = c;

    double B = d*y+e*x;

    double C = f*x*y + a*x*x + b*y*y - 1.0;

    double delta = B*B-4.0*A*C;

    if(delta < 0.0) return Mod+10.0;    //不在椭球上

    delta = sqrt(delta);

    double soz1 = (-B + delta)/(2.0*A);

    double soz2 = (-B - delta)/(2.0*A);

    if(dis(x,y,soz1) < dis(x,y,soz2))

        return soz1;

    return soz2;

}



double Simulated_Annealing()

{

    double x = 0,y = 0,z = sqrt(1.0/c);  //当前最优解

    double step = 1.0, rate = 0.99;

    while(step > eps)

    {

        for(int k=0;k<8;k++)

        {

            double kx = x + step*dx[k];

            double ky = y + step*dy[k];

            double kz = calc(kx,ky);

            if(kz >= Mod) continue;

            if(dis(kx,ky,kz) < dis(x,y,z))

            {

                x = kx,y = ky,z = kz;

            }

        }

        step *= rate;

    }

    return dis(x,y,z);

}



int main()

{

    while(scanf("%lf%lf%lf%lf%lf%lf",&a,&b,&c,&d,&e,&f)!=EOF)

    {

        printf("%.7f\n",Simulated_Annealing());

    }

    return 0;

}
View Code

 

你可能感兴趣的:(HDU)