HDU 2438 Turn the corner(三分)

Turn the corner


Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)

Total Submission(s): 1758    Accepted Submission(s): 658


Problem Description
Mr. West bought a new car! So he is travelling around the city.

One day he comes to a vertical corner. The street he is currently in has a width x, the street he wants to turn to has a width y. The car has a length l and a width d.

Can Mr. West go across the corner?

 

Input
Every line has four real numbers, x, y, l and w.
Proceed to the end of file.
 

Output
If he can go across the corner, print "yes". Print "no" otherwise.
 

Sample Input
  
  
10 6 13.5 4 10 6 14.5 4
 

Sample Output
  
  
yes no
 

Source

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


第一种思路:

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

如图中

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

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



AC代码:
<span style="font-family:KaiTi_GB2312;">#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;
}
</span>



第二种思路:

可以根据边界,汽车已经转弯,设水平方向为x轴,垂直方向为y轴。

则汽车的内边界(靠近里面的边界)的直线方程式f(x)为:y=x*tan(a)+l*sin(a)+d/cos(a).其中a是汽车与x轴的夹角

当y=X时,求解出的-x即为汽车的内边界到y轴的距离h,若h小于Y即可转弯,若大于Y就不能转弯。
所以只需要利用方程式,求-x的最大值,即可判断能否通过。

简单来讲,就是判断图中P点的横坐标的绝对值是否小于Y?小于,则可通过;否则,不可通过。

由于f(x)是凸函数(随着x的增大y先增大后减小),所以,需要借助三分求解。(对角度a在[0,90]三分)

图示:







AC代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
#define MIN 1e-7
#define PI acos(-1.0)
double x,y,l,d;

double Solve(double tmp){
    return (-x+l*sin(tmp)+d/cos(tmp))/tan(tmp);
}

int main(){
    while(~scanf("%lf%lf%lf%lf",&x,&y,&l,&d)){
        double low=0,high=PI/2.0,mid,mmid;
        if(x<d||y<d){ puts("no");continue; }
        while( high-low>MIN ){
            mid=(low+high)/2.0;
            mmid=(mid+high)/2.0;
            if(Solve(mid)>Solve(mmid))high=mmid+1e-9;
            else low=mid-1e-9;
        }
        if(Solve(mid)<y){
            puts("yes");
        }else 
            puts("no");
    }
    return 0;
}










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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值