POJ-1693: Counting Rectangles
keyword
平面走査法 座標圧縮 C++
問題概要
X軸に平行あるいは垂直な線分がS(<100)本与えられる。存在する長方形の数を数え上げる問題。
解法
まず座標圧縮する。その後は平面走査法でx座標の小さい方から舐めていく。計算量O(S^3)。
#include <cstdio> #include <vector> #include <set> #include <algorithm> using namespace std; struct segment{ int x1, y1, x2, y2; }; int S; int X, Y; segment segs[109]; int solve(){ vector< vector< vector<bool> > > segx(X, vector< vector<bool> >(Y, vector<bool>(Y, false))), segy(Y, vector< vector<bool> >(X, vector<bool>(X, false))); for(int i=0; i<S; i++){ if(segs[i].x1 == segs[i].x2){ int miny = min(segs[i].y1, segs[i].y2); int maxy = max(segs[i].y1, segs[i].y2); for(int j=miny; j < maxy; j++){ for(int k=j+1; k<=maxy; k++){ segx[segs[i].x1][j][k] = true; } } } else if(segs[i].y1 == segs[i].y2){ int minx = min(segs[i].x1, segs[i].x2); int maxx = max(segs[i].x1, segs[i].x2); for(int j=minx; j < maxx; j++){ for(int k=j+1; k<=maxx; k++){ segy[segs[i].y1][j][k] = true; } } } } int ans = 0; vector< vector<int> > dp(Y, vector<int>(Y,0)); for(int k=0; k<X; k++){ for(int i=0; i<Y; i++){ for(int j=i+1; j<Y; j++){ if(k==0 || (segy[i][k-1][k] && segy[j][k-1][k])){ if(segx[k][i][j]){ ans += dp[i][j]; dp[i][j]++; } } else { dp[i][j] = segx[k][i][j]?1:0; } } } } return ans; } int main(){ int M; scanf("%d", &M); for(int i=0; i<M; i++){ scanf("%d",&S); vector<int> xs, ys; for(int j=0; j<S; j++){ int x1, x2, y1, y2; scanf("%d%d%d%d",&x1,&y1,&x2,&y2); segs[j] = (segment){x1,y1,x2,y2}; xs.push_back(x1); xs.push_back(x2); ys.push_back(y1); ys.push_back(y2); } sort(xs.begin(), xs.end()); xs.erase(unique(xs.begin(), xs.end()), xs.end()); sort(ys.begin(), ys.end()); ys.erase(unique(ys.begin(), ys.end()), ys.end()); X = xs.size(); Y = ys.size(); for(int j=0; j<S; j++){ segs[j].x1 = distance(xs.begin(), lower_bound(xs.begin(), xs.end(), segs[j].x1)); segs[j].x2 = distance(xs.begin(), lower_bound(xs.begin(), xs.end(), segs[j].x2)); segs[j].y1 = distance(ys.begin(), lower_bound(ys.begin(), ys.end(), segs[j].y1)); segs[j].y2 = distance(ys.begin(), lower_bound(ys.begin(), ys.end(), segs[j].y2)); } printf("%d\n",solve()); } return 0; }