HDU 3756 三分

题目要求:
点在圆锥上或在圆锥里,求符合要求的最小体积的圆锥的高和半径。
解题思路:
把三维中的点转化到二维(可以设想成每个点在三维中距圆锥中心的距离和高)
线段上的点在圆锥曲面上,线段下的点在圆锥内部。
这样,只要找到一条能把全部点包括在内的,又符合题目要求的线就行了。
然后就是用三分在高的可能区域([lowHeight, highHeight])中查找
#include <iostream>
#include <cstdio>
#include <cmath>

using namespace std;

#define MAXSIZE 10010
#define HIGHHEIGHT 3000	// WA:修改上限
#define ACCURACY 1e-5	// WA:修改精度

typedef struct
{
	double x;
	double y;
}Point;

int nPoints;
Point point[MAXSIZE];

void Change(int i, double x, double y, double z);
double Radius(double height);
void Solve();
double LowHeight();
double Trisect(double lowHeight, double highHeight);
void Output(double height, double radius);

int main()
{
	double x, y, z;

	while (EOF != scanf("%d", &nPoints))
	{
		for (int i = 0; i < nPoints; i++)
		{
			scanf("%lf%lf%lf", &x, &y, &z);
			Change(i, x, y, z);
		}

		Solve();
	}

	return 0;
}

/*
 * 转换到二维
 * 把(x, y, z) 转换到 (sqrt(x^2 + y^2), 0, z) 去掉原来的y轴,即(sqrt(x^2 + y^2), y)
 */
void Change(int i, double x, double y, double z)
{
	point[i].x = sqrt(x * x + y * y);
	point[i].y = z;
}

/*
 * 求半径
 */
double Radius(double height)
{
	double radius = 0;

	for (int i = 0; i < nPoints; i++)
	{
		radius = max(radius, ((height * point[i].x) / (height - point[i].y)));
	}

	return radius;
}

void Solve()
{
	double lowHeight = LowHeight();
	double highHeight = HIGHHEIGHT;
	double height = Trisect(lowHeight, highHeight);	// 三分后得到的最终高度
	double radius = Radius(height);					// 最终半径

	Output(height, radius);
}

/*
 * 求高度下限
 */
double LowHeight()
{
	double lowHeight = 0;

	for (int i = 0; i < nPoints; i++)
	{
		lowHeight = max(lowHeight, point[i].y);
	}

	return lowHeight;
}

/**
 * 三分寻找合适的高
 * 三分搜索的区间是[lowHeight, highHeight]
 */
double Trisect(double lowHeight, double highHeight)
{
	double lowMid, highMid, lowRadius, highRadius;

	while (true)
	{
		lowMid = (lowHeight * 2 + highHeight) / 3;
		highMid = (lowHeight + highHeight * 2) /3;

		if (highMid - lowMid < ACCURACY)
		{
			break;
		}

		lowRadius = Radius(lowMid);
		highRadius = Radius(highMid);

		if (lowRadius * lowRadius * lowMid < highRadius * highRadius * highMid)
		{
			highHeight = highMid;
		}
		else
		{
			lowHeight = lowMid;
		}
	}

	return lowMid;
}

void Output(double height, double radius)
{
	printf("%.3lf %.3lf\n", height, radius);
}
Over
原文地址:https://www.cnblogs.com/submarinex/p/2004412.html