Time Limit: 10000/3000 MS (Java/Others)
Memory Limit: 32768/32768 K (Java/Others)

Problem Description

在一个广场上有一排沿着东西方向排列的石柱子,阳光从东边以一定的倾角射来(平行光)。有的柱子可能被在他东边的高大的柱子的影子给完全遮挡住了。现在你要解决的问题是求出有多少柱子是没有被完全遮挡住的。
假设每个石柱子是一根细棒,而且都垂直于地面摆放。
[HDU2540]遮挡判断

Input

输入包含多组数据。每组数据第一行是一个整数N(0<N<=100000)N(0<N<=100000),表示柱子的个数。N=0N=0代表输入结束。接下来有NN行,每行是两个整数,分别给出每根柱子的水平位置X和高度HHXX越大,表示越在西边,0<=X<=10000000,0<H<=100000000<=X<=10000000,0<H<=10000000保证不会有两根柱子在同一个X坐标上)。最后有一行,以分数的形式给出太阳光与地面的夹角的正切值T/A(1<=A,T<=10)T/A(1<=A,T<=10)

Output
对每组数据,输出包含所求数目的一行。

Sample Input

4
0 3
3 1
2 2
1 1
1/1
0

Sample Output

2

提示:
输入数据很多,请用scanf代替cin。

Source
UESTC 6th Programming Contest Online

题解:
单调栈
按照x的大小从小到大排序,从后往前依此入栈,每次入栈前要保证栈顶的柱子不会被当前放入栈的柱子给完全遮挡。
判断方法:
设当前栈顶的柱子为A,准备入栈的柱子为B
如果A的高度大于等于B,那么A一定不会被B遮挡。
否则
如果∠1的正切值大于等于T/A则A被B覆盖,
否则不被B覆盖
[HDU2540]遮挡判断最后输出栈内的元素总数即可

#include<bits/stdc++.h>
#define LiangJiaJun main
using namespace std;
int n;
struct Dic{
    int a,b;
}V;
struct Ds{
    int x,h;
}a[100004];
inline bool dex(Ds A, Ds B){
    return A.x<B.x;
}
Ds st[100004];
bool becover(Ds A,Ds B){
     if(A.h>=B.h)return 0;
     int g=B.h-A.h;
     int r=A.x-B.x;
     return g*V.b>=V.a*r;
}
int w33ha(){
    for(int i=1;i<=n;i++)scanf("%d%d",&a[i].x,&a[i].h);
    sort(a+1,a+n+1,dex);
    scanf("%d/%d",&V.a,&V.b);
    int t=1;
    st[t]=a[n];
    for(int i=n-1;i>=1;i--){
        while(t>0&&becover(st[t],a[i]))t--;
        st[++t]=a[i];
    }
    printf("%d\n",t);
    return 0;
}
int LiangJiaJun(){
    while(scanf("%d",&n)!=EOF){
        if(n==0)break;
        w33ha();
    }
    return 0;
}

相关文章: