HDU 5017 Ellipsoid(模擬退火)
阿新 • • 發佈:2019-02-09
Sample Output
1.0000000
【思路分析】
求橢球面上的點到原點的最短距離。網上很多說是模擬退火,個人感覺此題區域性最優解就是全域性最優解,即結果是一個單峰函式,頂多算個爬山演算法。
程式碼如下:
1.0000000
【思路分析】
求橢球面上的點到原點的最短距離。網上很多說是模擬退火,個人感覺此題區域性最優解就是全域性最優解,即結果是一個單峰函式,頂多算個爬山演算法。
程式碼如下:
#include <iostream> #include <cstdio> #include <cstdlib> #include <cmath> #include <cstring> #include <algorithm> using namespace std; #define r 0.99 #define inf 1e8 #define eps 1e-8 double a,b,c,d,e,f; int direction[10][2]; void init() { int x = 0; for(int i = -1;i <= 1;i++) { for(int j = -1;j <= 1;j++) { direction[x][0] = i; direction[x][1] = j; x++; } } } double distances(double x,double y,double z) { return sqrt(x * x + y * y + z * z); } double caculateZ(double x,double y)//根據求二次方程原理求z { double A = c; double B = d * y + e * x; double C = a * x * x + b * y * y + f * x * y - 1.0; double delta = B * B - 4.0 * A * C; if(delta < 0.0) return inf; else { double z1 = (-B + sqrt(delta)) / (2.0 * A); double z2 = (-B - sqrt(delta)) / (2.0 * A); if(distances(x,y,z1) < distances(x,y,z2)) return z1; else return z2; } } int main() { init(); while(scanf("%lf %lf %lf %lf %lf %lf",&a,&b,&c,&d,&e,&f) != EOF) { double x = 0,y = 0,z = sqrt(1.0 / c); double step = 1.0; while(step > eps) { for(int i = 0;i < 9;i++) { double x1 = x + step * direction[i][0]; double y1 = y + step * direction[i][1]; double z1 = caculateZ(x1,y1); if(z1 >= inf) continue; if(distances(x1,y1,z1) < distances(x,y,z)) { x = x1; y = y1; z = z1; } } step *= r; } printf("%.7lf\n",distances(x,y,z)); } return 0; }