poj 1689 && zoj 1422 3002 Rubbery (Geometry + BFS)

ZOJ :: Problems :: Show Problem

1689 -- 3002 Rubbery

  这题是从校内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 */
View Code

  做题最蛋疼的事情不能理解透题目的意思。做这题的时候,自己不停的出数据坑自己,可是出到那么恶心了都找不到bug。以后还要更加注意细节!

——written by Lyon

原文地址:https://www.cnblogs.com/LyonLys/p/poj_1689_zoj_1422_Lyon.html