poj 1689 && zoj 1422 3002 Rubbery (Geometry + BFS)
ZOJ :: Problems :: Show Problem
这题是从校内oj的几何分类里面找到的。
题意不难,就是给出一个区域(L,W),这个区域里面有很多多边形,多边形的边都是和x/y轴平行的。一个射线源在(L,0),射线是走平行于x/y轴的路径的。它们可以贴着多边形的边经过,不过不能穿过区域中的多边形,甚至不能从有至少一个交点的两条边之间穿过(区域边沿也一样)。射线只能向着x减少或者y增大的方向行走,问有多大的区域是没有射线经过的,不包括多边形区域。
做法就是,先将区域离散化成若干矩形,然后将每一个矩形看成一个点,构出图以后bfs射线就可以了。最后统计没有射线经过的区域大小即可。
做的时候注意,数组大小要控制好。如果射线源的位置在开始的时候就被覆盖了,可以直接计算没有多边形覆盖的面积。
代码如下:
1 #include <cstdio> 2 #include <iostream> 3 #include <algorithm> 4 #include <cstring> 5 #include <vector> 6 #include <map> 7 8 using namespace std; 9 10 const int N = 55; 11 const int M = N * N; 12 map<int, int> xid, yid; 13 bool blx[M >> 1][M >> 1], vis[M >> 1][M >> 1]; 14 typedef long long LL; 15 typedef pair<int, int> PII; 16 17 int L, W; 18 int rx[M], ry[M], xn, yn, pn[N]; 19 PII poly[N][N]; 20 21 void fix(int id) { 22 int mk = 0; 23 for (int i = 0; i < pn[id]; i++) if (poly[id][mk] < poly[id][i]) mk = i; 24 rotate(poly[id], poly[id] + mk, poly[id] + pn[id]); 25 } 26 27 const int dx[5] = { -1, -1, 0, 1, 0}; 28 const int dy[5] = { 1, 0, 1, 0, -1}; 29 30 inline LL cross(PII a, PII b) { return (LL) a.first * b.second - (LL) a.second * b.first;} 31 PII operator - (PII a, PII b) { return PII(a.first - b.first, a.second - b.second);} 32 33 bool inPoly(PII pt, int id) { 34 int wn = 0; 35 poly[id][pn[id]] = poly[id][0]; 36 for (int i = 0; i < pn[id]; i++) { 37 LL k = cross(poly[id][i + 1] - poly[id][i], pt - poly[id][i]); 38 int d1 = poly[id][i].second - pt.second; 39 int d2 = poly[id][i + 1].second - pt.second; 40 if (k > 0 && d1 <= 0 && d2 > 0) wn++; 41 if (k < 0 && d2 <= 0 && d1 > 0) wn--; 42 } 43 return wn != 0; 44 } 45 46 int qx[M * M >> 2], qy[M * M >> 2]; 47 inline bool inMat(int x, int y) { return 0 <= x && x < xn && 0 <= y && y < yn;} 48 49 void fill(int id) { 50 int cx = xid[poly[id][0].first] - 1; 51 int cy = yid[poly[id][0].second] - 1; 52 blx[cx][cy] = true; 53 int qh, qt, nx, ny; 54 qh = qt = 0; 55 qx[qt] = cx, qy[qt++] = cy; 56 while (qh < qt) { 57 cx = qx[qh], cy = qy[qh++]; 58 for (int i = 1; i < 5; i++) { 59 nx = cx + dx[i], ny = cy + dy[i]; 60 if (inMat(nx, ny) && !blx[nx][ny] && inPoly(PII(rx[nx] + rx[nx + 1] >> 1, ry[ny] + ry[ny + 1] >> 1), id)) { 61 blx[nx][ny] = true; 62 qx[qt] = nx, qy[qt++] = ny; 63 } 64 } 65 } 66 } 67 68 LL work(int n) { 69 int cx = xn - 1, cy = 0; 70 LL sum = 0; 71 int qh, qt, nx, ny; 72 memset(vis, 0, sizeof(vis)); 73 qh = qt = 0; 74 if (!blx[cx][cy]) { 75 qx[qt] = cx, qy[qt++] = cy; 76 vis[cx][cy] = true; 77 } 78 while (qh < qt) { 79 cx = qx[qh], cy = qy[qh++]; 80 for (int i = 1; i < 3; i++) { 81 nx = cx + dx[i], ny = cy + dy[i]; 82 if (inMat(nx, ny) && !blx[nx][ny] && !vis[nx][ny]) { 83 vis[nx][ny] = true; 84 qx[qt] = nx, qy[qt++] = ny; 85 } 86 } 87 } 88 for (int i = 0; i < xn; i++) { 89 for (int j = 0; j < yn; j++) { 90 if (vis[i][j] || blx[i][j]) continue; 91 sum += (LL) (rx[i + 1] - rx[i]) * (ry[j + 1] - ry[j]); 92 } 93 } 94 // for (int j = 0; j < yn; j++) { 95 // for (int i = 0; i < xn; i++) printf("%d", !vis[i][j] && !blx[i][j]); 96 // puts(""); 97 // } 98 // cout << "sum " << sum << endl; 99 return sum >> 2; 100 } 101 102 void PRE(int n) { 103 sort(rx, rx + xn); 104 xn = unique(rx, rx + xn) - rx; 105 xid.clear(); 106 for (int i = 0; i < xn; i++) xid[rx[i]] = i; 107 sort(ry, ry + yn); 108 yn = unique(ry, ry + yn) - ry; 109 yid.clear(); 110 for (int i = 0; i < yn; i++) yid[ry[i]] = i; 111 xn--, yn--; 112 // for (int i = 0; i < xn; i++) cout << i << '~' << rx[i] << endl; 113 // for (int i = 0; i < yn; i++) cout << i << '-' << ry[i] << endl; 114 // cout << xn << ' ' << yn << endl; 115 memset(blx, 0, sizeof(blx)); 116 for (int i = 0; i < n; i++) fix(i); 117 // for (int i = 0; i < pn[0]; i++) cout << poly[0][i].first << ' ' << poly[0][i].second << endl; 118 for (int i = 0; i < n; i++) fill(i); 119 // for (int j = 0; j < yn; j++) { 120 // for (int i = 0; i < xn; i++) printf("%d", blx[i][j]); 121 // puts(""); 122 // } 123 } 124 125 int main() { 126 // freopen("in", "r", stdin); 127 int T, n, x, y; 128 cin >> T; 129 while (T-- && cin >> L >> W) { 130 xn = yn = 0; 131 L <<= 1, W <<= 1; 132 rx[xn++] = L, ry[yn++] = W; 133 rx[xn++] = 0, ry[yn++] = 0; 134 cin >> n; 135 for (int i = 0; i < n; i++) { 136 cin >> pn[i]; 137 for (int j = 0; j < pn[i]; j++) { 138 scanf("%d%d", &poly[i][j].first, &poly[i][j].second); 139 poly[i][j].first <<= 1, poly[i][j].second <<= 1; 140 rx[xn++] = poly[i][j].first, ry[yn++] = poly[i][j].second; 141 } 142 } 143 PRE(n); 144 cout << work(n) << endl; 145 } 146 return 0; 147 } 148 149 /* 150 10 151 12 8 152 3 153 8 5 1 11 1 11 5 7 5 7 4 9 4 9 2 5 2 154 4 0 3 3 3 3 4 0 4 155 4 1 4 2 4 2 6 1 6 156 10 10 157 3 158 4 1 1 5 1 5 5 1 5 159 4 5 3 9 3 9 8 5 8 160 4 0 5 1 5 1 4 0 4 161 10 10 162 1 163 10 1 1 1 4 0 4 0 5 5 5 5 8 9 8 9 3 5 3 5 1 164 10 10 165 1 166 10 1 1 5 1 5 3 9 3 9 8 5 8 5 5 0 5 0 4 1 4 167 1000000 1000000 168 1 169 8 1 1 1 999999 2 999999 2 999998 999998 999998 999998 999999 999999 999999 999999 1 170 1000000 1000000 171 1 172 8 1 1 1 999999 2 999999 2 2 999998 2 999998 999999 999999 999999 999999 1 173 1000000 1000000 174 3 175 6 1 1 1 999999 2 999999 2 2 999999 2 999999 1 176 4 3 2 3 1000000 4 1000000 4 2 177 4 5 2 5 999999 6 999999 6 2 178 1000000 1000000 179 4 180 6 1 1 1 999999 2 999999 2 2 999999 2 999999 1 181 4 3 2 3 1000000 4 1000000 4 2 182 4 5 2 5 999999 6 999999 6 2 183 4 6 999999 7 999999 7 1000000 6 1000000 184 1000000 1000000 185 5 186 6 1 1 1 999999 2 999999 2 2 999999 2 999999 1 187 4 3 2 3 1000000 4 1000000 4 2 188 4 5 2 5 999999 6 999999 6 2 189 4 6 999999 7 999999 7 1000000 6 1000000 190 4 999999 1 999999 2 1000000 2 1000000 1 191 1000000 1000000 192 3 193 6 1 1 1 999999 2 999999 2 2 999998 2 999998 1 194 4 999999 3 999999 4 1000000 4 1000000 3 195 4 999999 3 999999 2 999998 2 999998 3 196 */
做题最蛋疼的事情不能理解透题目的意思。做这题的时候,自己不停的出数据坑自己,可是出到那么恶心了都找不到bug。以后还要更加注意细节!
——written by Lyon