您的位置:首页 > 产品设计 > UI/UE

HDU5033 - Building(暴力,DP思想)

2014-09-23 07:24 225 查看
题目链接 HDU5033

【题意】在直线上给出n幢房子的坐标和高度,求出人站在任意没有房子的位置上时能看到的天空的角度范围;房子坐标不会重复,并且保证人站的位置至少左右各有一座房子,注意坐标和高度是实数。

【分析】只要DP思想那样记录每个点左右两边斜率最高的那个点,然后查询的时候二分找查询点在哪两个点之间,再计算一遍左右两边最大的斜率即可求出答案,因为用了这个思想DP查询时间复杂度很低的,就算有极端数据斜率全部递减也不会很慢。比赛的时候竟然想着计算每个点高度为0时的左右最高斜率,一直WA到死,后来才发现一个是要减去当前高度后的斜率。

【AC CODE】546ms

#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
#define toj(a) (a*180.0/PI)
#define MAXN 100010
struct NODE{
double x, h;
bool operator<(const NODE& a) const{
return x < a.x;
}
}p[MAXN];
struct A{
int x;
double val;
}left[MAXN], right[MAXN];
const double PI = 4.0 * atan(1.0);
int n;

inline double clc_k(const NODE& a, const NODE& b){
return (a.h-b.h)/fabs(a.x-b.x);
}
int find(double num)
{
int l = 0, r = n-1, mid;
while(l <= r)
{
mid = (l+r)>>1;
if(p[mid].x < num)
l = mid+1;
else
r = mid-1;
}
return l;
}
int main()
{
#ifdef SHY
freopen("e:\\1.txt","r",stdin);
#endif
int t, count = 0;
scanf("%d%*c", &t);
while(t--)
{
scanf("%d%*c", &n);
for(int i = 0; i < n; i++)
scanf("%lf %lf%*c", &p[i].x, &p[i].h);
sort(p,p+n);
left[0].x = -1, left[0].val = 0;
for(int i = 1; i < n; i++)
{
int a = i-1;
while(~left[a].x && left[a].val > clc_k(p[a], p[i]))
a = left[a].x;
left[i].x = a;
left[i].val = clc_k(p[a], p[i]);
}
right[n-1].x = -1, right[n-1].val = 0;
for(int i = n-2; i >= 0; i--)
{
int a = i+1;
while(~right[a].x && right[a].val > clc_k(p[a], p[i]))
a = right[a].x;
right[i].x = a;
right[i].val = clc_k(p[a], p[i]);
}
int q;
NODE a;
a.h = 0;
scanf("%d%*c", &q);
printf("Case #%d:\n", ++count);
while(q--)
{
scanf("%lf%*c", &a.x);
int rt = find(a.x);
int lt = rt-1;
while(~left[lt].x && left[lt].val > clc_k(p[lt], a))
lt = left[lt].x;
while(~right[rt].x && right[rt].val > clc_k(p[rt], a))
rt = right[rt].x;
printf("%.10lf\n", 180-toj(atan(clc_k(p[lt],a)))-toj(atan(clc_k(p[rt],a))));
}
}
return 0;
}


 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  DP