HDU Turn the corner

 分析; 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;
}
/*

*/




 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值