现在的位置: 首页 > 综合 > 正文

hdu3756Dome of Circus && hdu2438 Turn the corner

2012年04月25日 ⁄ 综合 ⁄ 共 1785字 ⁄ 字号 评论关闭

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;
}

 

 

抱歉!评论已关闭.