hdu3756 Dome of Circus:三分学习

     这个题虽然是三维的,但是可以很容易的转化到二维去
。来看X-Z这个平面,我们将所有的点进行圆周映射,然后将所有的点都投影到
X-Z平面的的第一象限去,然后问题就转化成了在X-Z平面上找到一条斜率为负
的直线L,L和X正方向、Z正方向围成的三角形包含所有点,如果假设L和X轴的
交点为R,和Z轴焦点为H,要求pi*H*R^2的值最小。
   L这条线必定和某一
个给定的点擦边,也就是经过那个点,我们假设它经过P(a, b), 并且L的斜率
为K(K < 0),那么L的方程就可以表示为 L:  y = K * (x - a) + b,则H和R就
可以利用这个方程表示出来:

#include <stdio.h>
#include <math.h>

#define PI acos(-1.0)

typedef struct _point
{
	double x;
	double y;
	double z;

	double r;
}point;

point po[10001];
int n;
double maxR,maxZ;

double cal(double R)
{
	int i;
	double max = 0;
	for(i = 0; i < n; i ++)
	{
		double nz = po[i].z/(R - po[i].r);
		if(max < nz)max = nz;
	}
	return max * R;
}

int main(int argc, char *argv)
{
	//freopen("hdu_3756","r",stdin);
	int t;
	int i,j;
	scanf("%d",&t);
	while(t--)
	{
		scanf("%d",&n);
		maxR = maxZ = 0;
		for(i = 0; i < n; i ++)
		{
			scanf("%lf%lf%lf",&po[i].x,&po[i].y,&po[i].z);
			po[i].r = sqrt(po[i].x * po[i].x + po[i].y * po[i].y);
			if(maxR < po[i].r)maxR = po[i].r;
			if(maxZ < po[i].z)maxZ = po[i].z;
		}
		double right = 2*1e3, left = maxR, midl, midr;
		while(right - left > 1e-4)
		{
			midl = (right + 2*left)/3.0;
			midr = (left + 2*right)/3.0;
			double lans = cal(midl)*midl*midl;
			double rans = cal(midr)*midr*midr;
			if(lans < rans)right = midr;
			else left = midl;
		}
		double ans = (right + left)/2.0;
		printf("%.3lf %.3lf\n",cal(ans),ans);
	}
	//fclose(stdin);
	return 0;
}



H = -a * K + b;
R = -b / K + a;

你可能感兴趣的:(hdu3756 Dome of Circus:三分学习)