1. 程式人生 > >UVa 221 Urban Elevations 城市正視圖 離散化初步 無限化有限

UVa 221 Urban Elevations 城市正視圖 離散化初步 無限化有限

nat www 順序 main 高端 any tro record last

轉載請註明:

仰望高端玩家的小清新 http://www.cnblogs.com/luruiyuan/

題目大意:

題目傳送門:UVa 221 Urban Elevations

給出城市中建築物的x, y 坐標的最小值:x,y , 再給出其以左下角為坐標原點的關於x軸、y軸上的長度 w, 和 d,最後給出建築物的高度 h,將建築物的正視圖中,能夠看到的建築物的id打印出來:要求先打印x小的,當x相同時,打印y小的。為了簡化,假定建築物都是長方體。同時,每個輸出之間要用一個空行隔開 One blank line must separate output from consecutive input records.

(一開始沒註意審題,wa在這了┭┮﹏┭┮)

技術分享

思路:

首先,這個題我本來沒什麽思路,還是不得不參考一波劉汝佳老師的思路

本題最大的收獲是初步認識了 “離散化” :將無限轉化為有限的方法。

  1. 首先,我們註意到,每個建築物的深度在這裏沒有影響,因此深度是個幹擾項
  2. 一個關鍵點是,題目給定的數據是實數,即浮點數,因此我們不能窮舉所有的x坐標來遍歷,對於無窮問題,我們需要考慮離散化,化無窮為有限
  3. 對於本題,離散化的關鍵在於,如何表示建築物之間的互相重疊的關系
  4. 必須註意到,每個建築物有2個x坐標,一個是input中直接給出的x,而另一個是我們可以通過w+x得到的“右邊的x坐標”
  5. 通過2個坐標,我們可以首先對x去重,然後構建出相應的x軸的多個區間,這樣,每一組重疊關系必然會落在我們的x區間之中
    。這也正是代碼中x數組開2倍空間的原因,以及用途。
  6. 我們只需在區間內任選一點,即可作為區間的整體代表元素,來判斷某個建築是否經過了此區間,因此,可以選擇比較方便的區間中點。沒有經過區間代表元素的,顯然不會經過該區間經過了第5步和這一步,我們就將一個無限問題,轉化為有限問題了。
  7. 對於每個建築,我們考慮2點:是否經過了區間中點;是否存在y坐標小於它,且高度大於等於它的建築。上述兩點滿足任何一點,則該建築都不可見
  8. 其他小細節:代碼 53 行的 b[j].y < b[i].y 能夠保證 i != j; 53行的判定語句的順序也可以些微提高代碼效率,比如將函數調用延遲到最後一個,以降低調用概率,降低平均運行時間

代碼如下:

 1 // UVa 221 Urban Elevations
 2 // Ruiyuan Lu
 3 #include<cstdio>
 4 #include<algorithm>
 5 using namespace std;
 6 
 7 const int maxn = 100 + 5;
 8 double x[maxn*2];    // each building has 2 coordinates of x axis
 9 int n;                // number of the buildings
10 
11 struct Building{
12     int id;
13     double x, y, w, d, h;                             // w: means x_len, d:depth means y_len, h:height
14     bool operator < (const Building& b) const {        // sort for output
15         return x < b.x || (x == b.x && y < b.y);
16     }
17 }b[maxn];
18 
19 bool cover(int i, double mx);        // determine if the mx is in the range of building‘s x coordinate
20 bool visible(int i, double mx);        // i: the index of buildings; mx: middle x coordinate of an interval
21 
22 int main(){
23     int cnt = 0;
24     while(scanf("%d", &n) == 1 && n > 0){
25         for(int i=0; i<n;i++){
26             scanf("%lf%lf%lf%lf%lf", &b[i].x, &b[i].y, &b[i].w, &b[i].d, &b[i].h);
27             b[i].id = i + 1;
28             x[i*2] = b[i].x; x[i*2+1] = b[i].x + b[i].w;    // init x for discretization
29         }
30         sort(x, x+n*2);                        // sort before unique() is invoked
31         sort(b, b+n);                        // sort for output
32         int m = unique(x, x+maxn*2) - x;    // get the number of unique x in the array
33         // print result
34         if(cnt++)printf("\n");                // print the ‘\n‘ for last output
35         printf("For map #%d, the visible buildings are numbered as follows:\n%d", cnt, b[0].id);
36         for(int i=1;i<n;i++)
37             for(int j=1;j<m;j++)            // check each building if it is visible in any interval of m intervals
38                 if(visible(i, (x[j-1] + x[j]) / 2)){
39                     printf(" %d", b[i].id);
40                     break;
41                 }
42         printf("\n");                    // as they required: One blank line must separate output from consecutive input records.
43     }
44 }
45 
46 bool cover(int i, double mx){
47     return b[i].x <= mx && b[i].x + b[i].w >= mx;
48 }
49 
50 bool visible(int i, double mx){
51     if(!cover(i, mx)) return false;    
52     for(int j=0;j<n;j++)
53         if(b[j].y < b[i].y && b[j].h >= b[i].h && cover(j, mx)) return false;
54     return true;
55 }

技術分享

啦啦啦,今天就到這裏啦~改天見*★,°*:.☆( ̄▽ ̄)/$:*.°★* 。

UVa 221 Urban Elevations 城市正視圖 離散化初步 無限化有限