HDU 3756 三分
题目要求:
点在圆锥上或在圆锥里,求符合要求的最小体积的圆锥的高和半径。
解题思路:
把三维中的点转化到二维(可以设想成每个点在三维中距圆锥中心的距离和高)
线段上的点在圆锥曲面上,线段下的点在圆锥内部。
这样,只要找到一条能把全部点包括在内的,又符合题目要求的线就行了。
然后就是用三分在高的可能区域([lowHeight, highHeight])中查找
![](https://pic002.cnblogs.com/images/2011/266130/2011040316485439.png)
#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
/**************************************************************************
                 
原文来自博客园——Submarinex的博客: www.cnblogs.com/submarinex/               
 
*************************************************************************/