HDU

题意

给一个三维椭球面,求球面上距离原点最近的点。输出这个距离。

题解

模拟退火。

(z = f(x, y))函数写出来,这样通过随机抖动(x)(y)坐标就能求出(z)

代码

//#include <bits/stdc++.h>
#include <cstdio>
#include <cmath>
#include <ctime>
#include <algorithm>
#include <iostream>

#define FOPI freopen("in.txt", "r", stdin)
#define FOPO freopen("out.txt", "w", stdout)

using namespace std;
typedef long long LL;
const int maxn = 100 + 5;
const double eps = 1e-3;
const int inf = 0x3f3f3f3f;
const double start_T = 10000;

struct Point
{
    double x, y, z;
    Point() {}
    Point(double _x, double _y, double _z):x(_x), y(_y), z(_z) {}
};

double a, b, c, d, e, f;

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

int n;

double dist(Point a)
{
    return sqrt(a.x*a.x + a.y*a.y + a.z*a.z + 1e-8);
}

double getz(double x, double y)
{
    double A = c, B = d*y + e*x, C = a*x*x + b*y*y + f*x*y - 1;
    double delta = B*B - 4*A*C;
    if (delta < -eps) return inf+1;
    double z1 = (-B + sqrt(delta)) / 2 / A,
            z2 = (-B - sqrt(delta)) / 2 / A;
    return dist(Point(x, y, z1)) < dist(Point(x, y, z2)) ? z1 : z2;
}

double SA()
{
    Point p(0, 0, getz(0, 0)), to;
    double ans = dist(p), rate = 0.98, T = start_T;
    while(T > eps)
    {
        double fx, fy, fz;
        double tmp = inf;
        for (int aim = 0; aim < 8; aim++)
        {
            fx = (p.x+1.0*dx[aim]/start_T*T);
            fy = (p.y+1.0*dy[aim]/start_T*T);

            //printf("%f
", T);

            fz = getz(fx, fy);
            if (fz >= inf) continue;

            double d = dist(Point(fx, fy, fz));
            if (d < tmp)
            {
                tmp = d;
                to = Point(fx, fy, fz);
            }
        }

        if (tmp < ans)
        {
            ans = tmp;
            p = to;
        }
        else if ((rand()%10000)/10000.0 < exp((ans-tmp)/ T * start_T))
        {
            ans = tmp;
            p = to;
        }
        T *= rate;
    }
    return ans;
}

int main()
{
//    FOPI;
    srand(time(NULL));
    while(~scanf("%lf%lf%lf%lf%lf%lf", &a, &b, &c, &d, &e, &f))
        printf("%.7f
", SA());
}

原文地址:https://www.cnblogs.com/ruthank/p/10910504.html