標籤:include rectangle int ons clu return 維數 標記 blog
題意:
給定一個座標系, 給出n個矩形的左下角座標(bx,by)和右上方座標(tx,ty) , 求矩形覆蓋的面積, 有些地區會被多個矩形覆蓋, 但只用算一次。
n <= 1000, 0 <= bx,by,tx,ty <= 1e6
分析:
如果這題座標範圍很小的話, 其實可以直接開二維數組填充就好。
但因為座標太大,無法開這樣的數組,而且矩形數目不大,如果開這麼大的數組很可能造成浪費,所以我們可以考慮離散化去做這題。
我覺得離散化的核心就是——用點去表示線段。
我們可以將n個矩形的2n個座標離散化為nx個橫座標和ny縱座標,然後排序去重。
再從新掃描這n個矩形,找出那些離散點是在這些矩形內的,就標記。 最後就可以在這最多1000*1000個點內計算出面積。
代碼:
#include <iostream>#include <algorithm>#include <cstdio>#include <cstring>using namespace std;const int maxn = 2000 + 7;struct R{ int bx, by, tx, ty;}rec[maxn];int n;int nx = 0 , ny = 0;int X[maxn], Y[maxn];bool cover[maxn][maxn];int solve(){ sort(X,X+nx); sort(Y,Y+ny); int ux = unique(X,X+nx) - X;//排序,去重,用點表示線段, 就是離散化的核心 int uy = unique(Y,Y+ny) - Y;// cout << ux << " " << uy << "\n"; for(int i = 0; i < n ; i++){ int tx = lower_bound(X, X+ux, rec[i].bx) - X; // 找到左下角x對應的離散化點 int ty = lower_bound(Y, Y+uy, rec[i].by) - Y; // 找到左下角y對應的離散化點 for(int j = tx ; X[j] < rec[i].tx; j++){//calculate the area have covered. for(int k = ty; Y[k] < rec[i].ty; k++){ cover[j][k] = 1; //cover數組表示哪些離散化點是屬於矩形內的 } } } int area = 0; for(int i = 0; i < ux; i++){ for(int j = 0; j < uy; j++){ if(cover[i][j]){ area += (X[i+1]-X[i]) * (Y[j+1]-Y[j]); } } } return area;}int main(){// freopen("data.txt","r", stdin); while(~scanf("%d", &n)){ memset(cover,0,sizeof(cover)); nx = 0 , ny = 0; if(n == 0){ printf("*\n"); break; } for(int i = 0; i < n; i++){ scanf("%d %d %d %d", &rec[i].bx, &rec[i].by, &rec[i].tx, &rec[i].ty); X[nx++] = rec[i].bx, X[nx++] = rec[i].tx; Y[ny++] = rec[i].by, Y[ny++] = rec[i].ty; } printf("%d\n",solve()); }}
計蒜客 Overlapping Rectangles (離散化)