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
网上大牛思路:
可以根据边界,汽车已经转弯,设水平方向为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的最大值,即可判断能否通过。
由于f(x)是凸函数(随着x的增大y先增大后减小),所以,需要借助三分求解。
图示:
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cstdlib>
#include <string>
#include <cstring>
#include <cmath>
#include <algorithm>
#define N 10010
#define ll long long
#define eps 1e-7
#define pi acos(-1)
using namespace std;
double x, y, l, w;
double fun(double t)
{
return (-x+l*sin(t)+w/cos(t))/tan(t);
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("1.txt", "r", stdin);
#endif
ios::sync_with_stdio(false);
cin.tie(0);
int i, j, T;
double low, high, mid, mmid;
cout.setf(ios::fixed);
while(cin >> x >> y >> l >> w)
{
if (x < w || y < w)
{
cout << "no" << endl;
continue;
}
low = 0;
high = pi/2;
while(high -low > eps)
{
mid = (high+low)/2;
mmid = (mid+high)/2;
if(fun(mid)>fun(mmid)) high = mmid+1e-9;
else low = mid-1e-9;
}
if (fun(mid) < y)
cout << "yes" << endl;
else
cout << "no" << endl;
}
return 0;
}