思路:
一些解释:
①:建筑的排序:
下面是以输入顺序为标号,在数组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 }