天际线问题

问题描述 :
城市的天际线是从远处观看该城市中所有建筑物形成的轮廓的外部轮廓。现在,假设您获得了城市风光照片(图A)上显示的所有建筑物的位置和高度,请编写一个程序以输出由这些建筑物形成的天际线(图B)。
在这里插入图片描述

在这里插入图片描述
每个建筑物的几何信息用三元组 [Li,Ri,Hi] 表示,其中 Li 和 Ri 分别是第 i 座建筑物左右边缘的 x 坐标,Hi 是其高度。可以保证 0 ≤ Li, Ri ≤ INT_MAX, 0 < Hi ≤ INT_MAX 和 Ri - Li > 0。您可以假设所有建筑物都是在绝对平坦且高度为 0 的表面上的完美矩形。

例如,图A中所有建筑物的尺寸记录为:[ [2 9 10], [3 7 15], [5 12 12], [15 20 10], [19 24 8] ] 。
输出是以 [ [x1,y1], [x2, y2], [x3, y3], … ] 格式的“关键点”(图B中的红点)的列表,它们唯一地定义了天际线。关键点是水平线段的左端点。请注意,最右侧建筑物的最后一个关键点仅用于标记天际线的终点,并始终为零高度。此外,任何两个相邻建筑物之间的地面都应被视为天际线轮廓的一部分。

例如,图B中的天际线应该表示为:[ [2 10], [3 15], [7 12], [12 0], [15 10], [20 8], [24, 0] ]。

输入说明 :
首先输入建筑物的数量n
然后输入n行,每行是一座建筑物的几何信息三元组 [Li,Ri,Hi]
n在 [0, 10000] 范围内
建筑物列表按照Li 的x 坐标进行升序排列输入

输出说明 :
输出天际线表示,每个关键点一行,每行两个整数。
输出列表必须按关键点的 x 坐标升序排列输出。
输出天际线中不得有连续的相同高度的水平线。例如 […[2 3], [4 5], [7 5], [11 5], [12 7]…] 是不正确的答案;三条高度为 5 的线应该在最终输出中合并为一个:[…[2 3], [4 5], [12 7], …]

输入范例 :
5
2 9 10
3 7 15
5 12 12
15 20 10
19 24 8

输出范例 :
2 10
3 15
7 12
12 0
15 10
20 8
24 0

#include<iostream>
#include<vector>
#include<set>
using namespace std;
vector<vector<int>> getSkyline(vector<vector<int>> &buildings){
	multiset<pair<int, int>> all;
        vector<vector<int>> res;
        for (auto& e : buildings) {
            all.insert(make_pair(e[0], -e[2])); // critical point, left corner
            all.insert(make_pair(e[1], e[2])); // critical point, right corner
        }
        multiset<int> heights({0}); // 保存当前位置所有高度。
        vector<int> last = {0, 0}; // 保存上一个位置的横坐标以及高度
        for (auto& p : all) {
            if (p.second < 0) heights.insert(-p.second); // 左端点,高度入堆
            else heights.erase(heights.find(p.second)); // 右端点,移除高度
            // 当前关键点,最大高度
            auto maxHeight = *heights.rbegin();
            // 当前最大高度如果不同于上一个高度,说明这是一个转折点
            if (last[1] != maxHeight) {
                // 更新 last,并加入结果集
                last[0] = p.first;
                last[1] = maxHeight;
                res.push_back(last);
            }
        }
        return res;
}
int main(){
	int n;
	cin>>n;
	int x,y,z;
	vector<vector<int>> buildings;
	vector<int> tmp;
	for(int i=0;i<n;i++){
		cin>>x;
		cin>>y;
		cin>>z;
		tmp.push_back(x);
		tmp.push_back(y);
		tmp.push_back(z);
		buildings.push_back(tmp);
		tmp.clear();
	}
	vector<vector<int>> res=getSkyline(buildings);
	for(int i=0;i<res.size();i++){
		cout<<res[i][0];
		cout<<" ";
		cout<<res[i][1]<<endl;
	}
} 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值