1. 程式人生 > 其它 >2022.4.21 Uva 221

2022.4.21 Uva 221

 

 

這個題有一個我認為很有用的思想:離散化。

因為題中給出的座標不是整數,是無法一個個搜尋的,而且會很慢,所以可以記錄每個出現的x點,然後取每兩個的中點搜尋。

每個建築在該點的只有兩種狀態,即露出和不會露出。

資料處理上,因為資料保證正確,所以可以忽略掉深度這個資料,只使用高度和x方向,y方向只用於判斷前後關係。

#include<cstdio>
#include<algorithm>
#define maxn 105
using namespace std;
struct build
{
int id;
double x,y,w,d,h;
bool operator<(const build &a)const
{
return x<a.x||(x==a.x&&y<a.y);
}
}builds[maxn];
int n,m;
double xsum[maxn*2];
bool isin(int i,double x)
{
return builds[i].x<=x&&builds[i].x+builds[i].w>=x;
}
bool dfs(int i,double x)
{
if(!isin(i,x))
return false;
for(int k=0;k<n;k++)
{
if(isin(k,x)&&builds[k].y<builds[i].y&&builds[k].h>=builds[i].h)//檢測每個建築是否在這點的建築前並高於它
return false;
}
return true;
}
int main()
{
int kase=0;
while(scanf("%d",&n)&&n)
{
for(int i=0;i<n;i++)
{
scanf("%lf%lf%lf%lf%lf",&builds[i].x,&builds[i].y,&builds[i].w,&builds[i].d,&builds[i].h);
xsum[i*2]=builds[i].x;
xsum[i*2+1]=builds[i].x+builds[i].w;
builds[i].id=i+1;
}
sort(builds,builds+n);
sort(xsum,xsum+2*n);
m=unique(xsum,xsum+n*2)-xsum;//得到去重後的剩餘的元素數。去重原理是把重複元素移至陣列尾部,需要sort後使用。
if(kase++)
printf("\n");//多組資料換行。
printf("For map #%d, the visible buildings are numbered as follows:\n%d",kase,builds[0].id);
//第一個一定露出來。
for(int i=1;i<n;i++)
{
bool vis=false;
for(int j=0;j<m-1;j++)//遍歷每兩個x點的中點
{
if(dfs(i,(xsum[j]+xsum[j+1])/2))
{
vis=true;
break;
}
}
if(vis)
{
printf(" %d",builds[i].id);
}
}
printf("\n");
}
return 0;
}