题目链接
http://acm.hdu.edu.cn/showproblem.php?pid=5017
思路
裸的爬山啊!!网上一堆题解,一边代码里写的明明是爬山,一边标题上白纸黑字说是退火的是什么心态!代码还都差不多,我了个去
弄得我很naive地去写了个真退火,秒WA
代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <algorithm>
#include <cmath>
#define INF 1e12
#define EPS 1e-8
using namespace std;
double a,b,c,d,e,f;
double dist(double x,double y,double z) //求(x,y,z)到原点距离
{
return sqrt(x*x+y*y+z*z);
}
double calc(double x,double y) //已知x,y坐标,求z坐标
{
double delta=(d*y+e*x)*(d*y+e*x)-4*c*(a*x*x+b*y*y+f*x*y-1);
if(delta<0) //delta<0则方程无解
return INF;
double z1=(-d*y-e*x+sqrt(delta))/(2*c),z2=(-d*y-e*x-sqrt(delta))/(2*c);
if(dist(x,y,z1)<dist(x,y,z2)) return z1; //返回两个z中更优的那个
return z2;
}
int xx[]={0,0,1,-1,1,-1,1,-1},yy[]={1,-1,1,-1,-1,1,0,0};
double SA()
{
double T=1,x=0,y=0,z=sqrt(1/c); //当前最优解为(x,y,z)
double minans=dist(x,y,z);
while(T>EPS)
{
for(int dir=0;dir<8;dir++)
{
double newx=x+xx[dir]*T,newy=y+yy[dir]*T;
double newz=calc(newx,newy);
double nowans=dist(newx,newy,newz);
if(nowans<minans) //新的解更优,移动到新解上
{
minans=nowans;
x=newx,y=newy,z=newz;
}
}
T*=0.99;
}
return minans;
}
int main()
{
while(scanf("%lf%lf%lf%lf%lf%lf",&a,&b,&c,&d,&e,&f)!=EOF)
printf("%.7lf\n",SA());
return 0;
}