算法復習之坐標離散化
阿新 • • 發佈:2018-10-07
個數 find 寬度 ostream 利用 mes lan oid push
離散化概念
例子:
1.
描述: 在桌子上放了N個平行於坐標軸的矩形,這N個矩形可能有互相覆蓋的部分,求它們組成的圖形的面積。
輸入格式:輸入第一行為一個數N(1<=N<=100),表示矩形的數量,下面N行,每行四個整數,分別表示每個矩形的左下角
和右上角的坐標,坐標範圍為-10^8到10^8之間的整數。
輸出格式:
輸出只有一行,一個整數,表示圖形面積。
樣例輸入:
3
1 1 4 3
2 -1 3 2
4 0 5 2
樣例輸出:
10
#include<iostream> #include<algorithm> using namespace std; constint maxn=210; int x1[maxn],y1[maxn],x2[maxn],y2[maxn],x[maxn],y[maxn]; void init() { for(int i=0; i<maxn; i++) { x1[i]=y1[i]=x2[i]=y2[i]=x[i]=y[i]=0; } } int main() { int n; while(cin>>n) { init(); for(int i=1; i<=n; i++) { cin>>x1[i]>>y1[i]>>x2[i]>>y2[i]; x[2*i-1]=x1[i]; x[2*i]=x2[i]; y[2*i-1]=y1[i]; y[2*i]=y2[i]; } sort(x+1,x+2*n+1); sort(y+1,y+2*n+1); int sum=0; //枚舉每一個單位,,判斷是否符合條件 for(int i=1; i<=2*n-1; i++) for(int j=1; j<=2*n-1; j++) {int s=((x[i+1]-x[i])*(y[i+1]-y[i])); for(int k=1; k<=n; k++) { if(x[i]>=x1[k]&&y[i]>=y1[k]&&x[i+1]<=x2[k]&&y[i+1]<=y2[k]) { sum+=s; break; } } } cout<<sum<<endl; } return 0; }
2.來自《挑戰程序設計競賽》
區域的個數
w*h的各自上畫了n條垂直或水平的寬度為1的直線,求出這些線將格子劃分成了多少個區域。
限制條件:1<=w,h<=1000000 1<=n<=500
利用數組存儲搜索即可,問題在於數的範圍太大,所以要利用坐標離散化,數組中只需存儲有直線的行列,及其前後的行列就夠了。
//離散化函數,對坐標x1,x2進行離散化,並返回離散化之後的寬度 //其中x1,x2代表一條直線開頭與結尾的列 y為行 //重新形成一個數組 #include<iostream> #include<algorithm> #include<utility> #include<vector> int Compress(int *x1,int *x2,int w) { vector<int> s;//只需存前後及自身坐標 for(int i=0; i<n; i++) { for(int d=-1; d<=1; d++) { //首先判斷前後 int tx1=x1[i]+d; int tx2=x2[i]+d; if(1<=tx1&&tx1<=w) s.push_back(tx1); if(1<=tx2&&te2<=w) s.push_back(tx2); //進行排序刪除重復的 } } sort(s.begin(),s.end()); s.erase(unique(s.begin(),s.end()),s.end()); //重新分配順序 for(int i=0; i<n; i++) { x1[i]=find(s.begin(),s.end(),x1[i])-s.begin(); x2[i]=find(s.begin(),s.end(),x2[i])-s.begin(); } return s.size(); }
算法復習之坐標離散化