2020-12-22

如图所示,有n(n≤100)个建筑物。左侧是俯视图(左上角为建筑物编号,右下角 为高度),右侧是从南向北看的正视图。

输入每个建筑物左下角坐标(即x、y坐标的最小值)、宽度(即x方向的长度)、深度 (即y方向的长度)和高度(以上数据均为实数),输出正视图中能看到的所有建筑物,按 照左下角x坐标从小到大进行排序。左下角x坐标相同时,按y坐标从小到大排序。输入保证不同的x坐标不会很接近(即任意两个x坐标要么完全相同,要么差别足够大, 不会引起精度问题。分析:判断建筑物是否可见相当于判断南墙是否可见,可以忽略深度问题。将建筑物按照输出顺序排序,然后依次判断每个建筑物是否可见即可。举个例子,我们可以看下面这个栗子。 默认情况下假设上图中五个楼房的高度相同如果我们从南向北看,显然可以看到3号4号5号,那么如何让计算机来解决这个问题呢?那就来回顾一下我们的思路吧,我想正常情况下的思维应该是这样的,我使用枚举的方式从左往右看,从2号楼和4号楼的最左端一直到5号楼的最右端,看看建筑物是否在x轴的某个范围内可见。但是计算机没有办法这样处理问题,因为x坐标有无数多个,为了解决这个问题,我们可以想到使用离散化的方式,也就是说将无穷个x轴坐标转变成为有限个x坐标。那么具体的问题离散化的方式时什么呢?我们将小区从2号楼和4号楼的最左端一直到5号楼的最右端划分7个区间,可以一眼看出每一个区间只有存在楼房和不存在楼房这两种状态。我们可以看到2号楼和4号楼的x轴坐标都有重复,需要我们将x轴坐标排序后去除重复,那么任意的相邻的两个x坐标形成的区间就会有相同的属性,这样是需要在区间里面选择一个点,来判断这个点是否属于某一栋楼房的范围,我们可以选择终中点。那么问题来了,如何判断一个建筑物是否在某个x坐标处可见呢?首先就是建筑物中必须要包含这个x坐标嘛,且南边不能有另外一个建筑物也包含这个x坐标,且不能比他矮,也就是说,南面不能有跟它在用同一个区间内并且比它高的建筑物,这样的话只需要遍历所有的楼房即可。
#include<bits/stdc++.h>
using namespace std;
const int maxn=100+20;
struct Buildings{
int id;
double x,y,w,d,h;
bool operator < (const Buildings & rhs) const {
return x < rhs.x || (x==rhs.x&&y<rhs.y);
}
}b[maxn];
int n;
double x[maxn2];
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()
{
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[i
2]=b[i].x;
x[i2+1]=b[i].x+b[i].w;
b[i].id=i+1;
}
sort(b,b+n);
sort(x,x+n
2);
int m=unique(x,x+n*2)-x;
if(kase++) printf("\n");
printf(“楼房\n%d”,kase,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)){vis = true;break;}
}
printf("\n");
}
return 0;
}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值