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