标签:
题意: 给你 N 楼房, 然后给你m个人站在这些楼房之间, 问看到天空的仰角是多少度
思路: 对于每一个人, 算出左边的凸包, 和右边的凸包, 找出最大斜率点, 算角度即可
(我在线算比较费时, 离线可以省时间)
#include<iostream> #include<algorithm> #include<cstdio> #include<cstring> #include<cmath> using namespace std; const double INF=2e9; const int maxn = 1e5 + 131; const double PI = acos(-1.0); const double eps = 1e-8; struct Point { double x, y; int pos; Point(int x = 0,int y = 0): x(x), y(y) {} //Point(){} }; int dcmp(double x) { if(fabs(x) < eps) return 0; if(x < 0) return -1; else return 1; } typedef Point Vector; Vector operator + (Vector A, Vector B) { return Vector(A.x+B.x, A.y+B.y); } Vector operator - (Point A, Point B) { return Vector(A.x-B.x, A.y-B.y); } bool operator < (Point A, Point B) { return A.x < B.x; } int Cross(Vector A, Vector B) { return dcmp(A.x*B.y - A.y*B.x); } double Dot(Vector A, Vector B) { return double(A.x*B.x + A.y*B.y); } double Length(Vector A) { return sqrt(Dot(A, A)); } double Angle(Vector A, Vector B) { return acos(Dot(A,B) / Length(A) / Length(B)); } Point p[maxn], ch[maxn]; int PreL[maxn], PreR[maxn]; void ConVexHull(Point *p, int n, Point *ch) { int m = 0; PreL[0] = 0; for(int i = 0; i < n; ++i) { while(m > 1 && dcmp(Cross(ch[m-1] - ch[m-2], p[i]-ch[m-2]) > 0)) m--; ch[m++] = p[i]; if(i) PreL[i] = ch[m-2].pos; } m = 0; PreR[n-1] = n-1; for(int i = n-1; i >= 0; --i) { while(m > 1 && dcmp(Cross(ch[m-1] - ch[m-2], p[i]-ch[m-2]) < 0)) m--; ch[m++] = p[i]; if(n-1-i) PreR[i] = ch[m-2].pos; } } int lb(double xx,int n) { int left = 0, right = n; p[n].x = INF; while(left < right) { int mid=(left+right)>>1; if(xx<p[mid].x) right=mid; else left=mid+1; } return left-1; } int main() { int t; scanf("%d",&t); for(int kase = 1; kase <= t; ++kase) { int n; scanf("%d",&n); for(int i = 0; i < n; ++i) { scanf("%lf%lf", &p[i].x, &p[i].y); } sort(p,p+n); for(int i = 0; i < n; ++i) p[i].pos = i; ConVexHull(p,n,ch); /*for(int i = 0; i < n; ++i) cout << PreL[i] << " "; cout <<endl; for(int i = 0; i < n; ++i) cout << PreR[i] << " "; cout <<endl;*/ int Q; double pos; scanf("%d",&Q); printf("Case #%d:\n",kase); while(Q--) { scanf("%lf",&pos); int lll = lb(pos,n); int rrr = lll + 1; Point New(pos, 0); /*cout << New.x << " " << New.y <<endl; cout << p[lll].x << " " << p[lll].y << endl; cout << p[rrr].x << " " << p[rrr].y << endl; cout << "***********************\n"; cout << p[PreL[lll]].x << " " << p[PreL[lll]].y <<endl; cout << p[n-PreR[rrr]-1].x << " " << p[n-1-PreR[rrr]].y <<endl;*/ Vector L, R; while(dcmp(Cross(p[lll]-New, p[PreL[lll]]-New) < 0)) lll = PreL[lll]; L = p[lll]-New; while(dcmp(Cross(p[rrr]-New, p[PreR[rrr]]-New) > 0)) rrr = PreR[rrr]; R = p[rrr] - New; //cout << "L : \n" << L.x << " " << L.y<< endl; //cout << "R : \n" << R.x << " " << R.y<< endl; double Degree = fabs(Angle(L,R)*180 / PI); printf("%.10f\n",Degree); } } }
标签:
原文地址:http://www.cnblogs.com/aoxuets/p/4811215.html