• UVA-221 Urban Elevations(离散化)


    题意:

    给出建筑左下角的坐标和建筑的宽度(w)、高度(h)、长度(d),判断从南往北看,哪些建筑可以能够看到。

    思路:

    将建筑的左边界和右边界用一个x数组保存下来,然后按照题目要求进行排序、去重。

    这样处理之后的x数组中相邻两个数表示的区间是从南往北可以看到的。

    枚举每一个建筑,然后在这个建筑的基础上枚举每一个可以看到的区间,在这基础上在枚举判断这个建筑是不是被其他的建筑给挡住了,没有就输出这个建筑的id。

    看图可以理解对x数组进行排序去重的操作。

    #include <bits/stdc++.h>
    #define inf 0x3f3f3f3f
    #define MAX 1e9;
    #define FRE() freopen("in.txt","r",stdin)
    #define FRO() freopen("out.txt","w",stdout)
    using namespace std;
    typedef long long ll;
    typedef pair<int, int> P;
    const int maxn = 300;
    struct Build{
        double x,y,w,d,h;
        int id;
        bool operator<(const Build& bb)const{
            return x<bb.x || (x==bb.x && y<bb.y);
        }
    }b[maxn];
    double x[2*maxn];
    int n;
    
    bool Cover(int idx, double mx){//判断这个建筑的宽度内有没有这个中点mx
        return b[idx].x<=mx && (b[idx].x+b[idx].w)>=mx;
    }
    
    bool Visiable(int idx, double mx){
        if(!Cover(idx,mx))return false;//如果这个建筑的宽度内没有这个中点,就直接返回看不到
        for(int i = 0; i<n; i++){
            if(b[i].y<b[idx].y && b[i].h>=b[idx].h && Cover(i,mx)){
                return false;
            }
        }
        return true;
    }
    
    int main(){
        int cnt = 0;
        while(cin>>n&&n){
            for(int i = 0; i<n; i++){
                cin>>b[i].x>>b[i].y>>b[i].w>>b[i].d>>b[i].h;
                x[i*2] = b[i].x;//用x数组保存建筑的左边界
                x[i*2+1] = b[i].x+b[i].w;//用x数组保存建筑的右边界
                b[i].id = i+1;
            }
            sort(b,b+n);//对建筑按照题目的要求进行排序
            sort(x,x+2*n);//对x数组从小到大进行排序
            int m = unique(x,x+n*2)-x;//获得m个可以看到的区间,相邻的两个x数组的数表示一个区间
            if(cnt++){
                cout<<endl;
            }
            cout<<"For map #"<<cnt<<", the visible buildings are numbered as follows:"<<endl;
            cout<<b[0].id;//位于最左下角的建筑一定是可以看到的
            for(int i=1; i<n; i++){//枚举每一个建筑
                for(int j=0; j<m-1; j++){//枚举每一个可以看到的区间
                    if(b[i].x>x[j] || b[i].x+b[i].w<x[j+1])continue;//如果这个建筑直接不出现在这个区间中,就直接跳过
                    if(Visiable(i, (x[j]+x[j+1])/2.0)){//如果能看见就输出
                                                        //任取区间中的一个点(中点),如果建筑的宽度中有这个点
                        cout<<" "<<b[i].id;
                        break;
                    }
                }
            }
            cout<<endl;
        }
        return 0;
    }
    View Code
  • 相关阅读:
    堆栈的分布
    Socket网络编程(TCP/IP/端口/类)和实例
    c语言字节对齐
    理一理字节对齐的那些事
    Socket网络编程(TCP/IP/端口/类)和实例
    socket、端口、进程的关系
    SMT32 启动文件详细解说
    Chapter 1 First Sight——22
    Leetcode389
    Chapter 1 First Sight——21
  • 原文地址:https://www.cnblogs.com/sykline/p/10273316.html
Copyright © 2020-2023  润新知