思路:
一些解释:
①:建筑的排序:
下面是以输入顺序为标号,在数组bd中的顺序:
排序后在数组bd中的顺序:
以后我们比较就按这个顺序
②:x坐标的排序
x的内容是每一个建筑的左边界和右边界,我们把他去重排序后,就是一个一个的坐标,相邻的x形成一个区间,
取它的中点来判断,比如,样例输入的bd[1]就是遍历所有的区间来判断是否可见。下面附上调试截图。
x:
sort后的x:
unique后的x:
1 #include<cstdio> 2 #include<algorithm> 3 using namespace std; 4 struct building { 5 int NO; 6 double x, y, width, depth, height; 7 double xr;//右边界 8 }bd[105]; 9 double x[105 * 2]; 10 int n; 11 bool cmp(building & b1, building & b2) 12 { 13 if (b1.x < b2.x) 14 return true; 15 if (b1.x == b2.x&&b1.y < b2.y) 16 return true; 17 return false; 18 } 19 bool cover(int i, double mx)//看mx在不在第i个建筑范围内 20 { 21 return ((bd[i].x <= mx) && (bd[i].xr >= mx)); 22 } 23 bool visible(int i, double mx)//第i个建筑物在x=mx是否可见 24 { 25 if (!cover(i, mx)) 26 return false; 27 for (int j = 0; j < n; j++)//遍历所有建筑,寻找第i个建筑[南方]的建筑看会不会被挡住 28 { 29 if (bd[j].y < bd[i].y&&bd[j].height >= bd[i].height&&cover(j,mx)) 30 return false; 31 /*bd[j].y < bd[i].y在此建筑的南方 32 bd[j].height >= bd[i].height,南方建筑更高 33 cover(j,mx) mx也在南方建筑范围内 34 */ 35 } 36 return true; 37 } 38 int main() 39 { 40 int kase = 0; 41 while (scanf("%d", &n) && n != 0) 42 { 43 for (int i = 0; i < n; i++) 44 { 45 scanf("%lf%lf%lf", &bd[i].x, &bd[i].y, &bd[i].width); 46 scanf("%lf%lf", &bd[i].depth, &bd[i].height); 47 bd[i].NO = i+1; 48 bd[i].xr = bd[i].x + bd[i].width; 49 x[i * 2] = bd[i].x;//记录左边界 50 x[i * 2 + 1] = bd[i].xr;//右边界 51 } 52 53 sort(bd, bd + n, cmp); 54 sort(x, x + 2 * n); 55 int m = unique(x, x + n * 2) - x;//不重复元素的个数 56 if (kase++) 57 printf("\n"); 58 printf("For map #%d, the visible buildings are numbered as follows:\n%d", kase,bd[0].NO); 59 //因为第一个输出没有空格,而第一个bd肯定不会被挡住, 60 //所有先把第一个输出来.下面从1开始 61 for (int i = 1; i < n; i++) 62 { 63 bool vis = false; 64 for (int j = 0; j < m-1; j++) 65 { 66 if (visible(i, (x[j] + x[j+1]) / 2)) 67 { 68 vis = true; 69 break; 70 } 71 } 72 if (vis) 73 printf(" %d", bd[i].NO); 74 } 75 printf("\n"); 76 } 77 return 0; 78 }