UVA 221 Urban Elevations 离散化 模拟

题意:给出一张俯视图。给出N个建筑物的左下标,长度,宽度,高度。现在求,从南面看,能看到那些建筑?

思路:沿Y轴的宽度是没用的,直接忽略。

          然后,对左边先按x排序,在按y排序。我们分别判别那些建筑是可见的。

          对于可见,我们需要扫描整个区间,但因为这个是实数的区间,我们需要离散化。我们将每个建筑的左边边界和右边边界分别当成一个事件点。对所有的事件点进行排序。那么任意两个相近的事件点就是基本事件区间。对于这个基本事件区间,我们有以下性质:在这个基本的区间里,一个建筑要么完全可见,要么完全不可见。

         这样,我们对于每个建筑,扫描所有的基本事件区间,判断他在那个区间里可见,即该建筑在对应区间内,且在区间内位置比他靠前的建筑的高度斗殴比他小。

代码如下:

#include 
#include 
#include 

using namespace std;

const int MAX = 110;

int n;
double x[MAX<<1];

struct Building{
    int id;
    double x,y,w,d,h;
    bool operator < (const Building& rhs) const{
        return x < rhs.x || (x == rhs.x && y < rhs.y);
    }
} b[MAX];

bool cover(int i, double mx)
{
    return b[i].x <= mx && b[i].x + b[i].w >= mx;
}

bool visible(int i, double mx)
{
    if(!cover(i,mx)) return false;
    for(int k = 0; k < n; ++k)
        if(b[k].y < b[i].y && b[k].h >= b[i].h && cover(k,mx)) return false;
    return true;
}

int main(void)
{
    //freopen("input.txt","r",stdin);
    int cas = 0;
    while(scanf("%d", &n),n){
        for(int i = 0; i < n; ++i){
            scanf("%lf%lf%lf%lf%lf",&b[i].x,&b[i].y,&b[i].w,&b[i].d,&b[i].h);
            x[i<<1] = b[i].x, x[(i<<1)|1] = b[i].x+b[i].w;
            b[i].id = i + 1;
        }
        sort(b, b+n);
        sort(x,x + 2 * n);
        int m = unique(x,x + 2 * n) - x;

        if(cas++) puts("");
        printf("For map #%d, the visible buildings are numbered as follows:\n%d",cas,b[0].id);
        for(int i = 1; i < n; ++i){
            bool vis = false;
            for(int j = 0; j < m-1;++j)
            if(visible(i,(x[j] + x[j+1]) / 2.0)){
                vis = true;
                break;
            }
            if(vis) printf(" %d",b[i].id);
        }
        puts("");
    }
    return 0;
}


你可能感兴趣的:(模拟,搜索)