很巧妙的一道题,看了很长时间,也请教了同学。总之就是离散化的应用:
整体思路:
输入房子时,把左上角的X坐标和右上角X坐标输入到一个新的double数组中,作为一个拥有各个房子共同属性的X坐标,对他进行排序,去重(unique),这样只需要看每一个房子是否在这个区间是否可见就可以了,判断是否可见可以在这个区间里任意找一个点(原题是找中点),判断点是不是在房子里!
代码如下:
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn = 100 + 5;
int T,cont=0;
struct house
{
int id;
double x,y,wid,dep,hei;
}rhs[maxn];
bool cmp(const house &a,const house &b){
return (a.x<b.x)||(a.x==b.x && a.y<b.y);
}
bool cover(int id,double mx){
return (rhs[id].x <= mx) && (rhs[id].x+rhs[id].wid>=mx);
}
bool visible(int id,double mx){
if (!cover(id,mx))return false;
for (int i = 0; i < T; ++i)if (rhs[i].y < rhs[id].y && rhs[i].hei >= rhs[id].hei && cover(i,mx))return false;
return true;
}
int main()
{
double x[2*maxn];
while(scanf("%d",&T) == 1 && T){
for (int i = 0; i < T; ++i){
rhs[i].id=i+1;
scanf("%lf%lf%lf%lf%lf",&rhs[i].x,&rhs[i].y,&rhs[i].wid,&rhs[i].dep,&rhs[i].hei);
x[i*2]=rhs[i].x;x[i*2+1]=rhs[i].x+rhs[i].wid;//total 2T;
}
sort(rhs,rhs+T,cmp);
sort(x,x+2*T);
int m = unique(x,x+2*T)-x;
if (cont++)printf("\n");
printf("For map #%d, the visible buildings are numbered as follows:\n%d",cont,rhs[0].id);
for (int i = 1; i < T ; ++i){
for (int k = 0; k < m-1; ++k){
if (visible(i,(x[k]+x[k+1]) / 2.0)){printf(" %d",rhs[i].id);break;}
}
}
printf("\n");
}
return 0;
}