• 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
  • 相关阅读:
    Flask入门到精通(二)
    MySQL安装配置,命令,异常纪要
    JQuery 选择器
    redhat Enterprise Linux Server release 7.2(Maipo) 安装redis-stat
    pssh 不能执行指定用户命令
    VMware 命令行下安装以及导入Ubuntu系统
    Linux CPU相关信息查看
    Ubuntu 16.04 Mxnet CPU 版本安装
    Ubuntu 16.04 TensorFlow CPU 版本安装
    <转>揭秘DNS后台文件:DNS系列之五
  • 原文地址:https://www.cnblogs.com/submarinex/p/2004412.html
Copyright © 2020-2023  润新知