分析; 1.如果车w大于x或y, 必然不能转; 2.否则, 如果x> l或者y > l 则车肯定能转过;
3.如果1.2不成立, 那么 x和y都在范围[w, l]; 这样保证了凸转折点到车外侧的最近距离就是垂直距离;
车的外侧贴着墙壁走, 凸转折点到车外侧的距离是一个由大变小再变大的过程,
用三分法可以找到最小值, 如果 : 最小值 - w >=0 则可过去~
#include <iostream>
#include <cstdio>
#include <queue>
#include <cstring>
#include <cmath>
#include <vector>
#include <set>
#include <stack>
#include <algorithm>
//#include "myAlgorithm.h"
#define MAX 105
#define INF (1e8 + 5)
#define eps 1e-8
#define Rep(s, e) for( int i = s; i <= e; i++)
#define Cep(e, s) for( int i = e; i >= s; i --)
using namespace std;
double x, y, l, w;
//enum CT{aa}ct;
struct Point
{
double xx, yy;
Point(){}
Point &operator +(const Point &t)const{
Point c;
c.xx = t.xx + xx;
c.yy = yy + t.yy;
return c;
}
Point &operator -(const Point &t)const {
Point c;
c.xx = xx - t.xx; c.yy = yy - t.yy;
return c;
}
Point &operator * (const double w)const {
Point c;
c.xx = xx * w; c.yy = yy * w;
return c;
}
void set(double xx, double yy){
this->xx = xx;
this->yy = yy;
}
void show(){
cout<<xx<<" "<<yy<<endl;
}
}B, A, P, Q, M, S;
double gd(double width, double height) {
return sqrt(width * width + height * height);
}
double dotV(Point a, Point b)
{
return a.xx * b.xx + a.yy * b.yy;
}
double croV(Point a, Point b)
{
return a.xx * b.yy - a.yy * b.xx;
}
//bool inLine(const Point &p, const Point &a, const Point &b)///p 在ab方向上的前提下计算
//{
// return (p.xx >= a.xx && p.xx <= b.xx ||(p.xx >= b.xx && p.xx <= a.xx));
//}
//bool isNoAns;
//double make_Dist(double key)
//{
// Q.set(0, key); P.set(sqrt(l * l - key * key), 0);
// double k = P.xx / Q.yy, mxx = w * sqrt( 1 / (k* k + 1) );
// M.set(mxx, k * mxx); ///平移向量
Q.show();
P.show();
cout<<"k : "<<k<<endl;
M.show();
// B = P + M; A = Q + M;
cout<<"b:"<<endl;
B.show();
// //A.show();
//
// Point vb, va, vc, vd, D, ve, vf, vg, vh;
// vb = B - S, va = A - S; vc = A - B;///三条重要向量
//
// ve = B - S; vf = P - S; vg = A - S; vh = Q - S;
cout<<"vb : ";
vb.show();
// //va.show();
cout<<"vc : ";
vc.show();
// double r = - dotV(vc, vb)/ dotV(vc, vc);
cout<<"r : "<<r<<endl;
// vd.set(vc.xx * r + vb.xx, vc.yy * r + vb.yy);
cout<<"vd: ";
vd.show();
// D = S + vd;
cout<<"D : ";
D.show();
// double cres = croV(vb, va);
// if(cres <= 0)isNoAns = true;
// if(!inLine(D, B, A)){
// return INF;
// }
// return gd(vd.xx, vd.yy);
//}
//bool search()
//{
// double d = 0 , u = l, mid, mmid;
// while(u - d > eps){
// mid = ( d + u)/2, mmid = (mid + u)/2; ///靠右边找最小值
// double len1 = make_Dist(mid), len2 = make_Dist(mmid);
// if(isNoAns){ cout<<mid<<" crp bug "<<endl; return false;}
// cout<<len1<<"len1 len2"<<len2<<endl;
// cout<<mid<<"mid mmid"<<mmid<<endl;
// if(len1 < len2){///
// cout<<"right"<<endl;
// u = mmid;
// }else {
// cout<<"left"<<endl;
// d = mid;
// }
// }
// return true;
//}
//------------------, 用三分法, 向量计算相对关系, 但是公式想复杂了,算错, 瞬间凌乱了--------
//------------------, 换个思路求距离~~
//------跪了好久~~~>,< 是坐标系x方向相反, 求叉积的时候符号错了~~
double make_Dist001(double val)
{
Q.set(0, val); P.set( sqrt(l * l - val * val), 0);
Point vb, va, vc, vd, D;
// cout<<"s p q vb va :"<<endl;
// S.show(); P.show(); Q.show();
vb = P - S; va = Q - S; vc = Q - P;
// vb.show(); va.show();
double r = -dotV(vb , vc)/ dotV(vc , vc); /// (r *vc + vb) * (vc) = 0; => r = -(vc * vb)/(vc *vc);
D.set(r * vc.xx + P.xx, r * vc.yy + P.yy);
vd = D - S;
double len = gd(vd.xx, vd.yy);
double cres = croV(vb, va);
if(cres > 0){len = -len; }//cout<<"crp bug : len "<<len<<endl; vb.show(); va.show(); }///
return len - w;
}
bool tooYangtooSimple()///三分
{
S.set(y, x);
if( x < w || y < w )
return false;
if( x > l || y > l)
return true;
double d = 0, u = l, mid, mmid;
while(u - d > eps){
mid = (d + u)/2 , mmid = (mid + u)/2 ;///第二分朝右边
double len1 = make_Dist001(mid), len2 = make_Dist001(mmid);
if(len1 < 0 || len2 < 0)
return false;
if(len1 < len2){
u = mmid;///右边不符合
}else {
d = mid;///左边不符合
}
}
return true;
}
//----------------------
int main() {
//freopen("in.tx0t", "w", stdout);
while(cin>>x>>y>>l>>w) {
if(tooYangtooSimple()) {
puts("yes");
} else
puts("no");
}
return 0;
}
/*
*/