POJ 3962 (三分的利用)

Dome of Circus
Time Limit: 3000MS Memory Limit: 65536K
Total Submissions: 862 Accepted: 177 Special Judge

Description

A travelling circus faces a tough challenge in designing the dome for its performances. The circus has a number of shows that happen above the stage in the air under the dome. Various rigs, supports, and anchors must be installed over the stage, but under the dome. The dome itself must rise above the center of the stage and has a conical shape. The space under the dome must be air-conditioned, so the goal is to design the dome that contains minimal volume.
You are given a set of n points in the space; (x i, y i, z i) for 1 <= i <= n are the coordinates of the points in the air above the stage that must be covered by the dome. The ground is denoted by the plane z = 0, with positive z coordinates going up. The center of the stage is on the ground at the point (0, 0, 0).
The tip of the dome must be located at some point with coordinates (0, 0, h) with h > 0. The dome must have a conical shape that touches the ground at the circle with the center in the point (0, 0, 0) and with the radius of r. The dome must contain or touch all the n given points. The dome must have the minimal volume, given the above constraints.

Input

The first line of the input file contains a single integer number n (1 <= n <= 10 000) — the number of points under the dome. The following n lines describe points with three floating point numbers x i, y i, and z i per line — the coordinates of i-th point. All coordinates do not exceed 1000 by their absolute value and have at most 2 digits after decimal point. All zi are positive. There is at least one point with non-zero x i or y i.

Output

Write to the output file a single line with two floating point numbers h and r — the height and the base radius of the dome. The numbers must be precise up to 3 digits after decimal point.

Sample Input

 
#11 1.00 0.00 1.00
#22 1.00 0.00 1.00 0.00 1.50 0.50
#33 1.00 0.00 1.00 0.00 1.50 0.50 -0.50 -0.50 1.00

Sample Output

 
#13.000 1.500
#22.000 2.000
#32.000 2.000

Source




题意:题目给了n个点的X,Y,Z坐标,让你求一个体积最小的圆锥(圆锥的轴线是Z轴),使得圆锥可以覆盖所有的点(可以在内部,也可以在圆锥上)。

题目分析:先分析如何覆盖所有的点。因为该图是三维的不容易分析,但是根据圆锥的对称性,我们可以知道任何一点P,只要该点在所处的平面的圆上,就对结果没有影响。所以我们就把所有点以point[i].z为z坐标,point[i].r(即到z轴的距离)为x坐标,都投影到XOZ平面的第一象限。这样就使得我们只需要在XOZ平面内求一个三角形HOR将所有点都包含进出即可。圆锥的体积最小,也就是我们求得HOR三角形面积最小。

对三分如何求最小的面积说明一下:
我们从从三角形的定边r进行三分,通过函数solve来求出此时满足题意得最小h。(下面有注释).

下面对solve函数进行说明:
我们传过来的参数是定边边长r ,我们令方程y=k(x-r)(k<0) 即这个方程可以表示三角形的斜边与y轴的焦点即为h
假设点p(point[i].r,point[i].z)在斜边方程上即k=point[i].z/(point[i].r-r) ,因为k<0,即-k=point[i].z/(r-point[i].r),为了使三角形可以覆盖所有的点即我们就去更新k的值。
找到了满足所有题意得k值,我们就令x=0,因为k<0,所以就返回k*r.

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;

const int maxn=1e4+10;
const int inf=10010;//三分的上界
const double epx=1e-10;
const double PI=acos(-1.0);
double maxr;
int n;
struct note
{
    double x,y,z,r;
}point[maxn];

double solve(double r)//该函数是求出以r为底边满足能够覆盖所有点的最小的H
{
    double maxR=-1.0;
    for (int i=0;i<n;i++) {
        double res=point[i].z/(r-point[i].r);
        if (res>maxR) maxR=res;//更新k的数值
    }
    return maxR*r;
}
int main()
{
    while (scanf("%d",&n)!=EOF) {
        maxr=0.0;
        for (int i=0;i<n;i++) {
            scanf("%lf%lf%lf",&point[i].x,&point[i].y,&point[i].z);
            point[i].r=sqrt(point[i].x*point[i].x+point[i].y*point[i].y);
            if (maxr<point[i].r) maxr=point[i].r;//求出最大的point[i].r来决定三分的下界
        }
        double l=maxr,r=inf,mid,mmid; 
        while (r-l>=epx) {
            mid=(l+r)/2;
            mmid=(mid+r)/2;
            double h1=solve(mid);
            double h2=solve(mmid);
            if (h1*mid*mid<h2*mmid*mmid) { r=mmid; }//如果h2*mmid*mmid>h1*mid*mid证明最优解应该在mmmid的左边,令r=mmid;
            else {  l=mid;}//否则,在mid的右边,令l=mid;
        }
        printf("%.3f %.3f\n",solve(l),l);//(我自己被坑了,提交G++时,double型我用的%.3lf输出就错误,用%.3f就AC了)很苦恼.

    }
    return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值