一开始百科了一下模拟退火,没看明白
不知道为什么管这题的算法叫模拟退火,后来才发现本质跟模拟退火确实一样
就是在搜索解的过程中不断把搜索区间减小,一直到终止条件,比如<EPS
顺便说一下,模拟退火的复杂度不一定,对于这题来说,
0.99的1834次方会小于1e-8,复杂度很小,不过还是跑了140ms
#include <iostream>
#include <cstring>
#include <string>
#include <algorithm>
#include <cmath>
#include <vector>
#include <set>
#include <queue>
#include <map>
using namespace std;
#define INF 1e9
#define maxn
#define rep(i,x,y) for(int i=x;i<=y;i++)
#define mset(x) memset(x,0,sizeof(x))
#define eps 1e-8
typedef __int64 ll;
double a, b, c, d, e, f;
int dir[8][2] = {{1,0}, {-1,0}, {0,1}, {0,-1}, {1,1}, {1,-1}, {-1,1}, {-1,-1}};
double dist(double x, double y, double z){
return sqrt(x*x+y*y+z*z);
}
double cal(double x, double y){//已知x, y 求z
double A=c;
double B=d*y+e*x;
double C=a*x*x+b*y*y+f*x*y-1;
double delta = B*B-4*A*C;
if(delta<0) return 1e10;
delta = sqrt(delta);
double z1 = (-B+delta)/(2*A);
double z2 = (-B-delta)/(2*A);
if( dist(x, y, z1) < dist(x, y, z2) ) return z1;
return z2;
}
double SA(){
double x=0, y=0, z=sqrt(1.0/c);//初始点
double step=1.0, r=0.99;
while(step > eps){
for(int i=0; i<8; i++){
double xx = x+dir[i][0]*step;
double yy = y+dir[i][1]*step;
double zz = cal(xx, yy);
if(zz > INF) //无解
continue;
if(dist(xx, yy, zz) < dist(x, y, z)){
x = xx; y = yy; z = zz;
}
}
step *= r;
}
return dist(x, y, z);
}
int main(){
// freopen("a.txt","r",stdin);
// freopen(".out","w",stdout);
while(cin>>a>>b>>c>>d>>e>>f){
printf("%.8lf\n", SA());
}
return 0;
}