HDU - 5017 Ellipsoid (三分/模擬退火)

鏈接:https://cn.vjudge.net/problem/HDU-5017

題意:給出一個橢球面,求橢球面上原點最近的距離。

思路:首先,我們只需要考慮橢球的1/8(因爲它關於原點對稱。),然後,這1/8面上的點到原點的距離肯定是由遠到近再到遠,滿足三分的性質,直接三分即可。也可模擬退火。

1.三分

#include<bits\stdc++.h>
using namespace std;
#define ll long long
const double eps=1e-9;
double a,b,c,d,e,f;
double checkz(double x,double y)
{
	double A=c,B=d*y+e*x,C=a*x*x+b*y*y+f*x*y-1;
	double t=B*B-4*A*C,z1,z2;
	if(t<0) return 1e18;
	z1=(-B+sqrt(t))/(2*A),z2=(-B-sqrt(t))/(2*A);
	return sqrt(min(x*x+y*y+z1*z1,x*x+y*y+z2*z2));
}
double checky(double x)
{	
	double l=0,r=3/(2*sqrt(b)),m,lm,rm,templ,tempr,ans=1e18;
	while(r-l>eps)
	{
		lm=l+(r-l)/3;
		rm=r-(r-l)/3;
		templ=checkz(x,lm);
		tempr=checkz(x,rm);
		if(templ<=tempr)
		{
			r=rm;
			ans=min(ans,templ);
		}
		else
			l=lm;
	}	
	return ans;
}
int main()
{
	while(~scanf("%lf%lf%lf%lf%lf%lf",&a,&b,&c,&d,&e,&f))
	{
		double l=0,r=3/(2*sqrt(a)),lm,rm,ans=1e18,templ,tempr;
		while(r-l>eps)
		{	
			lm=l+(r-l)/3;
			rm=r-(r-l)/3;
			templ=checky(lm);
			tempr=checky(rm);
			if(templ<=tempr)
			{
				r=rm;
				ans=min(ans,templ);
			}
			else
				l=lm;
		}
		printf("%.7f\n",ans);
	}
	return 0;
 }

2.模擬退火

#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#define LL long long
using namespace std;
const double eps=1e-9;
int nex[4][2]={{0,1},{0,-1},{-1,0},{1,0}};
double a,b,c,d,e,f;
double dis(double xx,double yy)
{
	double aa=c,bb=d*yy+e*xx,cc=f*xx*yy+a*xx*xx+b*yy*yy-1;
    double dd=bb*bb-4*aa*cc;
    if(dd<0)  return -1;
    double z1=(-bb+sqrt(dd))/(2*aa);
    double z2=(-bb-sqrt(dd))/(2*aa);
    return sqrt(xx*xx+yy*yy+min(z1*z1,z2*z2));	
}
int main(void)
{
    while(~scanf("%lf%lf%lf%lf%lf%lf",&a,&b,&c,&d,&e,&f))
	{
		double xx,yy,ans,x=sqrt(1.0/a),y=0,t=1;
		while(t>eps)
		{
			ans=dis(x,y);
			int i;
			for(i=0;i<4;i++)
			{
				xx=x+t*nex[i][0];
				yy=y+t*nex[i][1];
				if(dis(xx,yy)<0)
					continue;
				if(ans-dis(xx,yy)>eps)	
					break;
			}
			if(i!=4)
			{
				x=xx;
				y=yy;
			}
			else
				t*=0.66;  
	    } 			
		printf("%.7f\n",ans);		
	}
	return 0;	
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章