点击打开题目链接
给出n个建筑物的左下角坐标和长,宽,高等属性。输出正视图中所有能看到的建筑物的标号,要求按照建筑物左下角坐标从小到大输出,x坐标相同时优先输出y小的。
思路:
将所有建筑物按照先x再y排序,然后对x坐标进行离散化处理。
即对所有x坐标排序去重,则相邻两个坐标区间只有一种状态,要么区间完全可见,要么完全不可见,取区间中点然后遍历所有建筑物,就能得出建筑物是否可见。
代码:
#include<bits/stdc++.h>
using namespace std;
const int maxn = 100 + 5;
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[maxn];
int n;
double x[maxn * 2];
int cover(int i, double mx) {
return b[i].x <= mx && b[i].x + b[i].w >= mx;
}
int is_visible(int i, double mx) {
if(!cover(i, mx)) return 0;
for(int j = 0; j < n; j++) {
if(cover(j, mx) && b[j].y < b[i].y && b[j].h >= b[i].h) return 0;
}
return 1;
}
int main() {
//ios::sync_with_stdio(false);
int kase = 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;
b[i].id = i + 1;
}
for(int i = 0; i < n ; i++) {
x[2 * i] = b[i].x, x[2 * i + 1] = b[i].x + b[i].w;
}
sort(b, b+ n);
sort(x, x + 2 * n);
int m = unique(x, x + 2 * n) - x; //x坐标去重之后的个数
if(kase++) cout << endl;
printf("For map #%d, the visible buildings are numbered as follows:\n%d", kase, b[0].id);
for(int i = 1; i < n; i++) {
int flag = 0;
for(int j = 0; j < m - 1; j++) {
if(is_visible(i, (x[j] + x[j+1]) / 2)) {flag = 1; break;}
}
if(flag) printf(" %d", b[i].id);
}
cout << endl;
}
return 0;
}