URAL 1436. Billboard(计算几何)

题意:给定一条线段,问从x轴上看这条线段的最大角度是多少。

三分枚举就ok了。。。。好纠结啊。。。应该分两段枚举。分别是线段的延长线与x轴的交点到负无穷。到正无穷。

应为坐标值小于1000可以证明x轴上的看点坐标小于2000.


#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <cmath>
#include <stack>
#include <map>
#include <string>
#define LL long long
#define DB double
using namespace std;
int x1,x2,y11,y2;
const DB EPS = 1e-12;
const DB INF = 1e20;
struct cpoint{
    DB x,y;
    cpoint(){}
    cpoint(DB a,DB b){x=a;y=b;}
};
cpoint a,b;
DB dot(cpoint a,cpoint b,cpoint p)
{
    return (a.x-p.x)*(b.x-p.x)+(a.y-p.y)*(b.y-p.y);
}
DB dist(cpoint a,cpoint b)
{
    return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
DB geta(cpoint a,cpoint b,cpoint p)
{
    return acos(dot(a,b,p)/dist(a,p)/dist(b,p));
}
DB oor(DB l,DB r)
{
    cpoint o1,o2;o1.y = 0.0;o2.y=0.0;
    DB mid,mmid,t1=-1,t2;
    while(r-l>EPS)
    {
        mid = (l+r)/2;
        mmid = (mid+r)/2;
        o1.x = mid;o2.x = mmid;
        t1 = geta(a,b,o1);
        t2 = geta(a,b,o2);
        if(t1<t2)
        {
            l = mid;
        }else
        {
            r = mmid;
        }
    }
    return t1;
}
void solve()
{
    DB x;
    if(y11!=y2)
    {
        x = ((x1-x2)*y11/(y2-y11)+x1);
    }else
    {
        x = 40009;
    }
    if(x>40009) x = 40009;
    if(x<-40009) x  = -40009;
    DB ans = max(oor(x,40009),oor(-40009,x));
    printf("%.6lf\n",ans);
}
int main()
{
    #ifndef ONLINE_JUDGE
    freopen("in.txt","r",stdin);
    #endif
    scanf("%d%d%d%d",&x1,&y11,&x2,&y2);
    if(y11*y2<=0)
    {
        printf("3.141593\n");
        return 0;
    }
    a = cpoint(x1,y11);
    b = cpoint(x2,y2);
    solve();
    return 0;
}


你可能感兴趣的:(计算几何)