// 题目 https://www.luogu.com.cn/problem/UVA221
/*
* 以左下角作为坐标原点
* 分析:
* 思路:将坐标离散化,化无穷为有穷
* 方法:将x轴分割为有限个区间(根据建筑物的坐标和宽度),
* 对于每一个建筑物判断其是否在某一段能露出来
* 判断方法:由于每个建筑物高度是水平的(即高度不变),因此只需在该区间上任取一点(取中点简单)
* 然后判断是否比他前面的建筑物高,只要该建筑物在某一区间能露出来就输出。
*/
#define _CRT_SECURE_NO_WARNINGS
#define LOCAL 1
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 100 + 5;
struct Building {
int id;
double x, y, w, d, h;
bool operator <(const Building& build) {
return x < build.x || (x == build.x && y < build.y);
}
}b[maxn];
int n; // n个建筑物
double x[maxn * 2]; //存放各个区间段
bool cover(int i, double mx) {
return b[i].x <= mx && (b[i].x + b[i].w) >= mx;
}
bool isvisible(int i, double mx) {
if (!cover(i, mx)) return false; //建筑物i不在该区段
for (int j = 0; j < n; j++) {
if(cover(j, mx)&&b[j].y<b[i].y&&b[j].h>=b[i].h)return false; //建筑物被挡住
}
return true;
}
int main()
{
#ifdef LOCAL
freopen("C:/Users/pyliu/代码/Visual stdio/语言篇/STL入门/竞赛题目/城市正视图 Urban Elevations/input.txt", "r", stdin);
#endif // LOCAL
int kase = 0;
while (scanf("%d", &n) == 1 && 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[2 * i] = b[i].x;
x[2 * i + 1] = b[i].x + b[i].w;
b[i].id = i + 1;
}
sort(b, b + n); // x坐标小的在前,x相同y值小的在前
sort(x, x + 2 * n);
// unique方法(将相邻重复元素放到数组后面)去除相邻重复元素,最后 m的值为去重后元素的个数
int m = unique(x, x + 2 * n) - x;
if (kase++) printf("\n");
printf("for map #%d, the visible buildings are numbered as follows:\n%d", kase,b[0].id);
for (int i = 1; i < n; i++) { //对剩下n-个建筑物判断
bool vis = false;
for (int j = 0; j < m - 1; j++) {
if (isvisible(i, (x[j] + x[j + 1]) / 2)) { vis = true; break; }
}
if (vis) printf(" %d", b[i].id);
}
printf("\n");
}
return 0;
}
城市正视图 Urban Elevations(UVa221)
最新推荐文章于 2024-07-19 19:11:19 发布