题意:给出n座大楼的位置以及高度,再给出m个人的位置,查询给出的人的位置所能看到的最大的仰角是多少。
思路:维护每两座的楼之间的斜率,使之成为一个凸面,用栈来维护,听了GG小伙伴的思路,可以将人当作高度为0的大楼来带入计算。
代码:
#include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> using namespace std; const int MAXN = 200005; const double pi = acos(-1.0); struct Build{ Build() { memset(ang, 0, sizeof(ang)); } double x, h; double ang[2]; bool pos; int id; }b[MAXN], q[MAXN]; int t, n, m; bool cmp1(Build a, Build b) { return a.x < b.x; } bool cmp2(Build a, Build b) { return a.id < b.id; } double deal(Build a, Build b) { double dx = fabs(b.x - a.x); double dy = b.h - a.h; return dy / dx; } int main() { int cas, t = 1; scanf("%d", &cas); while (cas--) { scanf("%d", &n); for (int i = 0; i < n; i++) { scanf("%lf%lf", &b[i].x, &b[i].h); b[i].pos = false; b[i].id = i; } scanf("%d", &m); for (int i = n; i < n + m; i++) { scanf("%lf", &b[i].x); b[i].h = 0; b[i].pos = true; b[i].id = i; } n += m; sort(b, b + n, cmp1); q[0] = b[0]; int top = 0; for (int i = 1; i < n; i++) { if (b[i].pos == false) { while (top && deal(b[i], q[top]) < deal(q[top], q[top - 1])) top--; q[++top] = b[i]; } else { int tmp = top; while (tmp && deal(b[i], q[tmp]) < deal(b[i], q[tmp - 1])) tmp--; b[i].ang[0] = deal(b[i], q[tmp]); } } q[0] = b[n - 1]; top = 0; for (int i = n - 2; i >= 0; i--) { if (b[i].pos == false) { while (top && deal(b[i], q[top]) < deal(q[top], q[top - 1])) top--; q[++top] = b[i]; } else { int tmp = top; while (tmp && deal(b[i], q[tmp]) < deal(b[i], q[tmp - 1])) tmp--; b[i].ang[1] = deal(b[i], q[tmp]); } } printf("Case #%d:\n", t++); sort(b, b + n, cmp2); for (int i = 0; i < n; i++) { if (b[i].pos == true) { double ans = pi - atan(b[i].ang[0]) - atan(b[i].ang[1]); ans = ans / pi * 180; printf("%.4lf\n", ans); } } } return 0; }
时间: 2024-10-07 14:21:34