zoukankan      html  css  js  c++  java
  • hdu3756Dome of Circus && hdu2438 Turn the corner

    hdu3756

    题意:在一个三维空间里,已知有N个点,求一个最小的圆锥使所有的点都包含其中。

    分析:主要有俩个步骤,首先就是将三维空间转化为二维空间,将所有的点都转化都同一个平面内考虑,通过将(X,Y,Z) 转化为(sqrt(x*x+y*y),Z),

    问题就转化为求一条直线将第一象限内的点全部包围起来。

    即,求满足条件的h,r 使得 h*r*r最小

    对于单调函数的表达式,我们可以采用二分搜索,但对于这种凸函数或凹函数求极值,我们可以采用三分搜索,给定h的上下限,三分h搜索即可。

    这里有三分搜索的介绍,挺不错的

    http://www.crazyhotice.com/2011/07/%E4%B8%89%E5%88%86%E6%90%9C%E8%8B%8F%E7%AE%97%E6%B3%95/

    核心代码:

     while(right-left > 1e-6)
      {
         lmid = (2.0*left+end)/3.0;
         rmid = (left+2.0*end)/3.0;
         if(f(lmid) < f(rmid))
             right = rmid;
         else
             left = lmid;
     }
    

      

    View Code
    #include<iostream>
    #include<algorithm>
    #include<math.h>
    using namespace std;
    #define MaxHeight 3000
    struct point
    {
    double x,y;
    }p[10005];
    int n;
    double get_r(double h)
    {
    double r=0.0;
    for(int i=0;i<n;i++)
    r=max(r,h*p[i].x/(h-p[i].y));
    return r;
    }
    double ThiDiv(double left,double right)
    {
    double lm,rm,lr,rr;
    while(right-left>1e-5)
    {
    lm=(left*2+right)/3.0;
    rm=(right*2+left)/3.0;
    lr=get_r(lm);
    rr=get_r(rm);
    if(lr*lr*lm<rr*rr*rm)
    right=rm;
    else left=lm;
    }
    return left;
    }
    int main()
    {
    int T;
    scanf("%d",&T);
    while(T--)
    {
    scanf("%d",&n);
    double x,y,low=0.0;
    for(int i=0;i<n;i++)
    {
    scanf("%lf %lf %lf",&x,&y,&p[i].y);
    p[i].x=sqrt(x*x+y*y);
    if(p[i].y>low)
    low=p[i].y;
    }
    double h=ThiDiv(low,MaxHeight);
    printf("%.3f %.3f\n",h,get_r(h));
    }
    return 0;
    }

     另一道三分的题目,

    hdu2438

    题意:已知汽车的长和宽,l和w,以及俩条路的宽为x和y,汽车所处道路宽为x ,问汽车能否顺利转弯?

    分析:汽车能否顺利转弯取决于在极限情况下,随着角度的变化,汽车离对面路的距离是否大于等于0

    如图中

    在上图中需要计算转弯过程中h 的最大值是否小于等于y

    很明显,随着角度θ的增大,最大高度h先增长后减小,即为凸性函数,可以用三分法来求解

    View Code
    #include<iostream>
    #include<algorithm>
    #include<math.h>
    using namespace std;
    #define pi 3.141592653
    double x,y,l,w;
    double cal(double a)
    {
    double s=l*cos(a)+w*sin(a)-x;
    double h=s*tan(a)+w*cos(a);
    return h;
    }
    int main()
    {
    while(scanf("%lf %lf %lf %lf",&x,&y,&l,&w)!=EOF)
    {
    double left=0.0,right=pi/2;
    double lm,rm;
    while(fabs(right-left)>1e-6)
    {
    lm=(left*2.0+right)/3.0;
    rm=(left+right*2.0)/3.0;
    if(cal(lm)>cal(rm))
    right=rm;
    else left=lm;
    }
    if(cal(left)<=y)
    printf("yes\n");
    else printf("no\n");
    }
    return 0;
    }
  • 相关阅读:
    机器学习入门-贝叶斯垃圾邮件过滤(原理)
    机器学习入门-贝叶斯拼写纠错实例
    机器学习入门-贝叶斯算法(原理)
    机器学习入门-集成算法(bagging, boosting, stacking)
    高并发网站技术架构
    Nginx教程
    Shell脚本部分语法
    关于文本处理sort-cut-wc详解
    vim操作命令
    修改Linux基本配置
  • 原文地址:https://www.cnblogs.com/nanke/p/2348041.html
Copyright © 2011-2022 走看看