AOJ 0531 坐标离散化
涂色:(日文题目,自己翻译成了中文)为了宣传信息竞赛,要在长方形的三合板上喷油漆来制作招牌。三合板上不需要涂色的部分预先贴好了护板。被护板隔开的区域要涂上不同的颜色,比如上图就应该涂上5种颜色。
请编写一个程序计算涂色数量,输入数据中,保证看板不会被护板全部遮住,并且护板的边一定是水平或垂直的。
输入:
第一个数是宽w(1 ≤ w ≤ 1000000),第二个数是高h(1 ≤ h ≤ 1000000)。
第二行是护板的数量n(1 ≤ n ≤ 1000),接着n行是每个护板的左下角坐标 (x1 , y1 )和右上角坐标 (x2 , y2 ),用空格隔开: x1 , y1 , x2 , y2 (0 ≤ x1< x2 ≤ w, 0 ≤ y1 < y2 ≤ h 都是整数)
招牌的坐标系如下,左下角是 (0, 0) ,右上角是(w, h) , 测试集中的30%都满足w ≤ 100, h ≤ 100, n ≤ 100。
输出:
一个整数,代表涂色数量。
使用坐标离散化求解。
坐标离散化的思想是:当坐标范围很大而坐标数量很少时,可以考虑把所有用到的横坐标排序,然后用每个坐标对应的下标来更新坐标位置。
举例来说:
这个例子中的用到的横坐标有1,2,4,5,6,7,9,10,11,12,13,14。
那么横坐标对(1,5)就可以转化为(0,3)。节省了一位空间,这个节省在空隙变大后会越来越明显。
通过坐标离散化,通常时间复杂度就可以降到令人满意的程度了。
这里使用了imos法,进一步优化时间复杂度。
接下来是代码,来自http://www.hankcs.com/program/algorithm/aoj-0531-paint-color.html
1 #include<iostream> 2 #include<vector> 3 #include<algorithm> 4 #include<queue> 5 #include <cstring> 6 #define MAX_N 1000 + 16 7 8 using namespace std; 9 10 int N, H, W; 11 int X1[MAX_N], X2[MAX_N], Y1[MAX_N], Y2[MAX_N]; 12 int fld[2 * MAX_N][2 * MAX_N], // 填充遍历用,代表坐标(i, j)处是否空白(压缩后) 13 dx[4] = { 1, -1, 0, 0 }, dy[4] = { 0, 0, 1, -1 }; 14 15 // 压缩坐标,将坐标的值变成“这是第几种值”,返回一共有几种坐标 16 int compress(int *x1, int *x2, int w) 17 { 18 vector<int>xs; 19 20 for (int i = 0; i < N; ++i) 21 { 22 int tx1 = x1[i], tx2 = x2[i]; 23 if (1 <= tx1 && tx1 < w) xs.push_back(tx1); 24 if (1 <= tx2 && tx2 < w) xs.push_back(tx2); 25 } 26 xs.push_back(0); 27 xs.push_back(w); 28 sort(xs.begin(), xs.end()); 29 xs.erase(unique(xs.begin(), xs.end()), xs.end()); 30 for (int i = 0; i < N; ++i) 31 { 32 x1[i] = find(xs.begin(), xs.end(), x1[i]) - xs.begin(); 33 x2[i] = find(xs.begin(), xs.end(), x2[i]) - xs.begin(); 34 } 35 return xs.size() - 1; 36 } 37 38 int bfs() 39 { 40 int ans = 0; 41 for (int i = 0; i < H; ++i) 42 { 43 for (int j = 0; j < W; ++j) 44 { 45 if (fld[i][j]) continue; 46 ++ans; 47 queue<pair<int, int> >que; 48 que.push(make_pair(j, i)); 49 while (!que.empty()) 50 { 51 int nx = que.front().first, ny = que.front().second; 52 que.pop(); 53 54 for (int i = 0; i < 4; ++i) 55 { 56 int tx = nx + dx[i], ty = ny + dy[i]; 57 if (tx < 0 || W < tx || ty < 0 || H< ty || fld[ty][tx] > 0) continue; 58 que.push(make_pair(tx, ty)); 59 fld[ty][tx] = 1; 60 } 61 } 62 } 63 } 64 return ans; 65 } 66 67 ///////////////////////////SubMain////////////////////////////////// 68 int main(int argc, char *argv[]) 69 { 70 while (cin >> W >> H, W | H) 71 { 72 cin >> N; 73 for (int i = 0; i < N; ++i) 74 { 75 cin >> X1[i] >> Y1[i] >> X2[i] >> Y2[i]; 76 } 77 78 memset(fld, 0, sizeof(fld)); 79 80 W = compress(X1, X2, W); 81 H = compress(Y1, Y2, H); 82 83 // imos-法 84 for (int i = 0; i < N; i++) 85 { 86 fld[Y1[i]][X1[i]]++; 87 fld[Y1[i]][X2[i]]--; 88 fld[Y2[i]][X1[i]]--; 89 fld[Y2[i]][X2[i]]++; 90 } 91 // 横向累积 92 for (int i = 0; i < H; i++) 93 { 94 for (int j = 1; j < W; j++) 95 { 96 fld[i][j] += fld[i][j - 1]; 97 } 98 } 99 // 纵向累积 100 for (int i = 1; i < H; i++) 101 { 102 for (int j = 0; j < W; j++) 103 { 104 fld[i][j] += fld[i - 1][j]; 105 } 106 }// 累积完后,fld中非0部分表示有挡板 107 cout << bfs() << endl; 108 } 109 return 0; 110 } 111 ///////////////////////////End Sub//////////////////////////////////
posted on 2018-05-03 21:06 Best_Efforts 阅读(318) 评论(0) 编辑 收藏 举报