题意:给定一条线段,问从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;
}