Ellipsoid

HDU

题意:给定一个椭球面\(ax^2+by^2+cz^2+dyz+exz+fxy=1\)\(a,b,c,d,e,f\),求椭球面上一点到\((0,0,0)\)的最短距离.

距离公式直接由二维推广到三维的.这题我真的搞了一个多小时,一直连样例都过不去,交一发结果A了???我浪费那么多时间干嘛呢???这题公式都告诉你了,就可以直接套模板不断调试各种参数了.

哦哦,还是要讲一下如何确定椭球面上一个点\((x,y,z)\),随机搞出\(x,y\)之后,\(z\)要根据上面的公式算出.变形一下上面的公式就是\(cz^2+(dy+ex)z+ax^2+by^2+fxy-1=0\),直接运用公式法求解二元一次方程即可.

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<map>
#include<set>
using namespace std;
double a,b,c,d,e,f,ansx,ansy,ansz;
const double inf=1e18;
inline double dist(double x,double y,double z){
	return sqrt(x*x+y*y+z*z);
}
inline double calc(double x,double y){
	double A=c,B=e*x+d*y,C=a*x*x+b*y*y+f*x*y-1.0;
	double delta=B*B-4.0*A*C;//公式啊
    if(delta<0)return inf;//初中知识啊
	double z1=(-B+sqrt(delta))/(2.0*A),z2=(-B-sqrt(delta))/(2.0*A);
	if(dist(x,y,z1)<dist(x,y,z2))return z1;//两个解选最优的
	return z2;
}
inline void mnth(){
	double T=2333,eps=1e-15;
	while(T>eps){
		double nowx=ansx+(rand()*2-RAND_MAX)*T;
		double nowy=ansy+(rand()*2-RAND_MAX)*T;
		double nowz=calc(nowx,nowy);
		if(nowz==inf){T*=0.997;continue;}
		double delta=dist(nowx,nowy,nowz)-dist(ansx,ansy,ansz);
		if(delta<0)ansx=nowx,ansy=nowy,ansz=nowz;
		else if(exp(delta/T)*RAND_MAX<rand())ansx=nowx,ansy=nowy,ansz=nowz;
		T*=0.997;
	}
}
int main(){
	//srand((int)time(NULL));//HDU应该是不支持这个
	srand(19260817);//随便搞个数就行
	while(scanf("%lf%lf%lf%lf%lf%lf",&a,&b,&c,&d,&e,&f)!=EOF){
		ansx=0;ansy=0;ansz=sqrt(1.0/c);
		mnth();printf("%.10lf\n",dist(ansx,ansy,ansz));
	}
    return 0;
}

posted on 2019-10-13 21:54  PPXppx  阅读(268)  评论(0编辑  收藏  举报