1. 題目
X星球的一批考古機器人正在一片廢墟上考古。
該區域的地面堅硬如石、平整如鏡。
管理人員為方便,建立了標准的直角坐標系。
每個機器人都各有特長、身懷絕技。它們感興趣的內容也不相同。
經過各種測量,每個機器人都會報告一個或多個矩形區域,作為優先考古的區域。
矩形的表示格式為(x1,y1,x2,y2),代表矩形的兩個對角點坐標。
為了醒目,總部要求對所有機器人選中的矩形區域塗黃色油漆。
小明並不需要當油漆工,只是他需要計算一下,一共要耗費多少油漆。
其實這也不難,只要算出所有矩形覆蓋的區域一共有多大面積就可以了。
注意,各個矩形間可能重疊。
本題的輸入為若干矩形,要求輸出其覆蓋的總面積。
輸入格式:
第一行,一個整數n,表示有多少個矩形(1<=n<10000)
接下來的n行,每行有4個整數x1 y1 x2 y2,空格分開,表示矩形的兩個對角頂點坐標。
(0<= x1,y1,x2,y2 <=10000)
輸出格式:
一行一個整數,表示矩形覆蓋的總面積面積。
例如,
輸入:
3
1 5 10 10
3 1 20 20
2 7 15 17
程序應該輸出:
340
再例如,
輸入:
3
5 2 10 6
2 7 12 10
8 1 15 15
程序應該輸出:
128
資源約定:
峰值內存消耗(含虛擬機) < 256M
CPU消耗 < 2000ms
請嚴格按要求輸出,不要畫蛇添足地打印類似:“請您輸入...” 的多余內容。
注意:
main函數需要返回0;
只使用ANSI C/ANSI C++ 標准;
不要調用依賴於編譯環境或操作系統的特殊函數。
所有依賴的函數必須明確地在源文件中 #include <xxx>
不能通過工程設置而省略常用頭文件。
提交程序時,注意選擇所期望的語言類型和編譯器類型。
2. 分析
2.1 如何計算面積
因為坐標全是整數,這樣就可以用比較簡單的方法--記錄坐標
但是會有TLE的問題,請自行取舍。
以下是一個簡單的圖例:

給出了x和y這兩個對角的坐標,由於全是整數(離散),我們可以直接用兩個for循環來計算面積。
2.2 輸入坐標的兩種可能
對角有兩種情況,我們若想使用坐標法求面積,必須統一從左下角往右上角遍歷,因此需要把兩種類型的對角統一變成左下-右上形式的。方法如下:
2.3 如何解決重疊問題
我的想法是比較簡單的:建立一個10000*10000的bool型二維數組,對於每次輸入的坐標,將對應區域內的bool設為true,最后厲遍統計true的數量就是面積。
void Print(int x1, int y1, int x2, int y2, bool plain[][10001]) { //第一種方法
int xBegin = min(x1,x2); //這是左下角的x int yBegin = min(y1,y2); //這是左下角的y int xEnd = max(x1,x2); //這是右上角的x int yEnd = max(y1,y2); //這是右上角的y for (int i=xBegin; i<xEnd; i++) { for (int j=yBegin; j<yEnd; j++) { plain[i][j] = true;//暴力置位 } } }
無腦暴力,最為致命。這樣做的好處是:你根本不用考慮重復的問題,因為同一個位置設置多少次也不會有任何改變,可以放心使用。當然,必須要注意的是,10000*10000的數組是會爆棧的,必須用new分配堆內存給該變量。
或者你也可以使用STL里面的set:構造一個字符串,格式為xxx-yyy,其中xxx為x坐標,yyy為y坐標,之后將其插入集合中,由於同樣的坐標具有一樣的形式,無法重復插入,最后只需要輸出set.size()就能得到答案。(該方法不容易爆,推薦使用)
void Print(int x1, int y1, int x2, int y2, set<string> &st) { //第二種方法,注意&不要漏了
int xBegin = min(x1,x2); int yBegin = min(y1,y2); int xEnd = max(x1,x2); int yEnd = max(y1,y2); for (int i=xBegin; i<xEnd; i++) { for (int j=yBegin; j<yEnd; j++) { ostringstream s; string str; s.clear(); s << i; str += s.str(); str += '-'; s.clear(); s << j; str += s.str(); st.insert(str); } } }
3. 代碼
1 #include <iostream>
2 #include <sstream>
3 #include <fstream>
4 #include <algorithm>
5 #include <vector>
6 #include <set>
7 #include <list>
8 #include <string>
9 #include <map>
10 #include <cmath>
11 #include <cstring>
12 #include <cstdlib>
13 #include <windows.h>
14
15 using namespace std;
16
17
18 void Print(int x1, int y1, int x2, int y2, set<string> &st); 19 #define DEBUG 1 //當你使用官方的txt測試數據時,可以將該宏置位,並在第27行更改文件名,這樣就可以從txt讀入測試數據,最后自行對照對應的out.txt 20 21 22 int main() { 23 set<string> st; 24 int n,x1,y1,x2,y2,count; 25 long time = GetTickCount(); 26 #if DEBUG 27 ifstream fin( "in1.txt" ,ios::in); 28 fin >> n; 29 for (int i=0; i<n; i++) { 30 fin >> x1 >> y1 >> x2 >> y2; 31 Print(x1,y1,x2,y2,st); 32 count = st.size(); 33 } 34 #else 35 cin >> n; 36 for (int i=0; i<n; i++) { 37 cin >> x1 >> y1 >> x2 >> y2; 38 Print(x1,y1,x2,y2,st); 39 count = st.size(); 40 } 41 #endif 42 time = GetTickCount() - time; //計算時間 43 cout << st.size() << endl <<"time:" << time << " ms" << endl; 44 return 0; 45 } 46 47 void Print(int x1, int y1, int x2, int y2, set<string> &st) { 48 int xBegin = min(x1,x2); 49 int yBegin = min(y1,y2); 50 int xEnd = max(x1,x2); 51 int yEnd = max(y1,y2); 52 for (int i=xBegin; i<xEnd; i++) { 53 for (int j=yBegin; j<yEnd; j++) { 54 ostringstream s; 55 string str; 56 57 s.clear(); 58 s << i; 59 str += s.str(); 60 str += '-'; 61 s.clear(); 62 s << j; 63 str += s.str(); 64 st.insert(str); 65 } 66 } 67 }
4. 運行結果





最后兩個嚴重TLE,尤其是是第五個測試點,不過答案至少是對了,能拿不少分。
待我更多學習之后再來優化。
