计算几何(空间几何 + 三分) - Dome of Circus - UVA 1473

计算几何(空间几何 + 三分) - Dome of Circus - UVA 1473

题意:

空 间 中 给 出 n 个 点 , 要 求 用 一 个 底 面 在 x O y 平 面 , 顶 点 在 z 轴 正 半 轴 的 圆 锥 包 含 这 n 个 点 。 空间中给出n个点,要求用一个底面在xOy平面,顶点在z轴正半轴的圆锥包含这n个点。 nxOyzn

要 求 这 圆 锥 的 体 积 最 小 , 计 算 此 时 圆 锥 的 底 面 半 径 和 高 。 要求这圆锥的体积最小,计算此时圆锥的底面半径和高。

输入:

多 组 测 试 数 据 , 多组测试数据,

每 组 首 行 包 括 一 个 正 整 数 n , 表 示 点 的 个 数 , 每组首行包括一个正整数n,表示点的个数, n

接 着 n 行 每 行 包 括 3 个 浮 点 数 x , y , z , 表 示 点 的 坐 标 。 接着n行每行包括3个浮点数x,y,z,表示点的坐标。 n3x,y,z

输出:

两 个 浮 点 数 , 分 别 表 示 圆 锥 的 高 和 底 面 半 径 。 两个浮点数,分别表示圆锥的高和底面半径。

小 数 点 后 保 留 三 位 。 小数点后保留三位。

Sample Input

1
1.00 0.00 1.00
2
1.00 0.00 1.00
0.00 1.50 0.50
3
1.00 0.00 1.00
0.00 1.50 0.50
-0.50 -0.50 1.00

Sample Output

3.000 1.500
2.000 2.000
2.000 2.000

数据范围:

1 ≤ n ≤ 10000 1 ≤ n ≤ 10000 1n10000


分析:

不 难 发 现 , 半 径 越 大 、 高 越 大 , 就 越 容 易 包 含 所 有 点 。 不难发现,半径越大、高越大,就越容易包含所有点。

圆 锥 的 体 积 应 当 满 足 一 个 单 峰 的 凹 函 数 , 故 我 们 考 虑 用 三 分 法 来 求 这 个 最 小 值 。 圆锥的体积应当满足一个单峰的凹函数,故我们考虑用三分法来求这个最小值。

我 们 三 分 半 径 , 对 于 每 次 三 分 得 到 的 两 个 半 径 r 1 和 r 2 , 我们三分半径,对于每次三分得到的两个半径r_1和r_2, r1r2

我 们 通 过 比 例 关 系 计 算 出 , 每 个 半 径 对 应 的 , 能 够 覆 盖 所 有 点 的 圆 锥 的 高 h 1 和 h 2 , 如 下 图 我们通过比例关系计算出,每个半径对应的,能够覆盖所有点的圆锥的高h_1和h_2,如下图 h1h2

在这里插入图片描述
对 于 每 一 个 点 P ( x , y , z ) , 利 用 相 似 三 角 形 的 性 质 , 有 如 下 等 式 : 对于每一个点P(x,y,z),利用相似三角形的性质,有如下等式: P(x,y,z)

x 2 + y 2 r = h − z h \frac{\sqrt{x^2+y^2}}{r}=\frac{h-z}{h} rx2+y2 =hhz

解 得 : 解得:

h = z ⋅ r r − x 2 + y 2 h=\frac{z·r}{r-\sqrt{x^2+y^2}} h=rx2+y2 zr

那 么 h = m a x i = 1 n { z i ⋅ r r − x i 2 + y i 2 } 那么h=max_{i=1}^n\{\frac{z_i·r}{r-\sqrt{x_i^2+y_i^2}}\} h=maxi=1n{rxi2+yi2 zir}

最 后 三 分 输 出 极 值 点 处 的 底 面 半 径 和 高 即 可 。 最后三分输出极值点处的底面半径和高即可。

代码:

#include<cstring>
#include<iostream>
#include<cmath>
#include<cstdio>
#include<algorithm>

using namespace std;

const double eps=1e-10;
const double pi=cos(-1.0);

int dcmp(double x)
{
    if(fabs(x)<eps) return 0;
    else return x<0 ? -1 : 1;
}

struct Point3
{
    double x,y,z;
    Point3(double x=0,double y=0,double z=0) : x(x), y(y), z(z) {}
    bool operator < (const Point3 &t) const
    {
        return z<t.z;
    }
};

int n;
Point3 V[10010];

double check(double r)
{
    double h=0;
    for(int i=0;i<n;i++)
    {
        double d=sqrt(V[i].x*V[i].x+V[i].y*V[i].y);
        h=max(h,V[i].z/(r-d)*r);
    }
    return h;
}

int main()
{
    while(~scanf("%d",&n))
    {
        double L=0,R=1e20;
        for(int i=0;i<n;i++) scanf("%lf%lf%lf",&V[i].x,&V[i].y,&V[i].z);

        while(R-L>eps)
        {
            double lmid=(L+R)/2, rmid=(lmid+R)/2;
            double h1=check(lmid), h2=check(rmid);
            double v1=1.0/3.0*pi*lmid*lmid*h1, v2=1.0/3.0*pi*rmid*rmid*h2;
            if(v1>v2) L=lmid;
            else R=rmid;
        }
        
        printf("%.3lf %.3lf\n",check(L),L);
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
计算几何 目录 ㈠ 点的基本运算 1. 平面上两点之间距离 1 2. 判断两点是否重合 1 3. 矢量叉乘 1 4. 矢量点乘 2 5. 判断点是否在线段上 2 6. 求一点饶某点旋转后的坐标 2 7. 求矢量夹角 2 ㈡ 线段及直线的基本运算 1. 点与线段的关系 3 2. 求点到线段所在直线垂线的垂足 4 3. 点到线段的最近点 4 4. 点到线段所在直线的距离 4 5. 点到折线集的最近距离 4 6. 判断圆是否在多边形内 5 7. 求矢量夹角余弦 5 8. 求线段之间的夹角 5 9. 判断线段是否相交 6 10.判断线段是否相交但不交在端点处 6 11.求线段所在直线的方程 6 12.求直线的斜率 7 13.求直线的倾斜角 7 14.求点关于某直线的对称点 7 15.判断两条直线是否相交及求直线交点 7 16.判断线段是否相交,如果相交返回交点 7 ㈢ 多边形常用算法模块 1. 判断多边形是否简单多边形 8 2. 检查多边形顶点的凸凹性 9 3. 判断多边形是否凸多边形 9 4. 求多边形面积 9 5. 判断多边形顶点的排列方向,方法一 10 6. 判断多边形顶点的排列方向,方法二 10 7. 射线法判断点是否在多边形内 10 8. 判断点是否在凸多边形内 11 9. 寻找点集的graham算法 12 10.寻找点集凸包的卷包裹法 13 11.判断线段是否在多边形内 14 12.求简单多边形的重心 15 13.求凸多边形的重心 17 14.求肯定在给定多边形内的一个点 17 15.求从多边形外一点出发到该多边形的切线 18 16.判断多边形的核是否存在 19 ㈣ 圆的基本运算 1 .点是否在圆内 20 2 .求不共线的三点所确定的圆 21 ㈤ 矩形的基本运算 1.已知矩形三点坐标,求第4点坐标 22 ㈥ 常用算法的描述 22 ㈦ 补充 1.两圆关系: 24 2.判断圆是否在矩形内: 24 3.点到平面的距离: 25 4.点是否在直线同侧: 25 5.镜面反射线: 25 6.矩形包含: 26 7.两圆交点: 27 8.两圆公共面积: 28 9. 圆和直线关系: 29 10. 内切圆: 30 11. 求切点: 31 12. 线段的左右旋: 31 13.公式: 32

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值