zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    golang 的几个入门资料
    docker 容器网络基础
    nginx 容器反向代理网址的设置
    【知乎Live】狼叔:如何正确的学习Node.js
    nginx资料汇总
    web 框架
    work behind corp proxy
    [转载] 历史上前端领域的重要技术革命
    前后端要不要分离以及如何做
    微电子工艺基础知识讲解(集成电路历史/厂商/产业链)
  • 原文地址:https://www.cnblogs.com/submarinex/p/2004412.html
Copyright © 2011-2022 走看看